编译原理分析器大作业之字幕分析器
创始人
2024-05-10 09:11:39
0

        写这篇文章的主要目的呢是分享一下编译原理大作业——电影字幕分析器,分享一下我的做法,可能采用的做法不是特别好的用法,希望各位多多指点,觉得文章不错给点小赞赞喔!!!

题目介绍

写一个srt字幕解释器,需要分析单词和语法,分别写出词法和语法,实现字幕的偏移,检验字幕单词语义。

字幕解释器功能与设计问题说明:

  1. 分析字幕的单词和语法,分别写出词法和语法的文法
  2. 在文法的基础上设计词法分析器和语法分析器
  3. 建立内存数据结构,缓冲字幕
  4. 实现字幕平移(例如,将字幕整体推迟2秒)等功能,更新字幕文件

分析

文法分析

我们先来看一条字幕的结构:

0

00:00:01,000 --> 00:00:25,000

English subtitle by : Eduun

1

00:00:36,700 --> 00:00:38,700

The late fourth century A.D. the

Roman Empire began to crumble.

通过上面我们可以看到该文法的大致结构为第一行为序号,第二行内容为时间,第三行为字幕内容,因此,我们可以先简单定义对应的语法和语义为,其中d---数字, 词法分析程序可以接受输入参数,如,d(2)表示数字只能是2位,d(0)表示数字不限位数

d(0)

d(2):d(2):d(2),d(3) --> d(2):d(2):d(2),d(3)

c

nn

d(0)

d(2):d(2):d(2),d(3) --> d(2):d(2):d(2),d(3)

c

代码实现

首先对于字幕我们需要用一个实体来文件中的记录,包括字幕的序号,字幕出现时间、字幕结束时间、字幕内容

public class SRT {private Integer id;private Integer beginTime;private Integer endTime;private String srtBody;
}

时间偏移的实现用一个TimeMove来实现,具体的思想是当需要偏移时间时,我们在原先的基础上加上需要偏移的时间:

public class TimeMove {int hour;int minute;int second;int msecond;public long getMilliSecond() {return (hour * 3600L + minute * 60L + second) * 1000L + msecond;}
}

上面是主要的功能设计,然后下面我们需要对字幕文件进行解析,将内容保存进内存中,对于字幕的内容我们直接将内容拼接了起来,防止有多行字幕,对于时间的解析,我单独封装了一个方法来进行专门解析,对于空行我们就用一个@去分隔

public void parseSrt(String srtPath){FileInputStream inputStream;try {inputStream = new FileInputStream(srtPath);} catch (FileNotFoundException e) {e.printStackTrace();return;// 有异常,就没必要继续下去了}BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));String line;srtMap = new TreeMap<>();StringBuilder sb = new StringBuilder();int key = 0;try {while ((line = br.readLine()) != null || sb.length() > 0) {if (!"".equals(line) && line != null) {sb.append(line).append("@");continue;}String[] parseStrs = sb.toString().split("@");// 该if为了适应一开始就有空行以及其他不符格式的空行情况if (parseStrs.length < 3) {continue;}SRT srt = new SRT();StringBuilder srtBody = new StringBuilder();TimeToken timeToken = new TimeToken(srt);// 可能1句字幕,也可能2句及以上。srt.setId(Integer.valueOf(parseStrs[0].trim()));timeToken.parseTime(parseStrs[1]);// 删除最后一个"\n"for (int i = 2; i < parseStrs.length; i++) {srtBody.append(parseStrs[i], 0, parseStrs[i].length() - 1);}srt.setSrtBody(new String(srtBody.toString().getBytes(), StandardCharsets.UTF_8));srtMap.put(key, srt);key++;// 清空,否则影响下一个字幕元素的解析sb.delete(0, sb.length());}} catch (Exception e) {e.printStackTrace();}
}

/*** startTime   -->     endTime* 解析时间* @param timeToken 时间的句子*/
public void parseTime(String timeToken) {StringBuilder sb = new StringBuilder();List list = new ArrayList<>();for (int i = 0; i < timeToken.length(); i++) {if (isToken(timeToken.charAt(i))) {if (sb.length() == 0 || sb.length() < 12) {continue;}list.add(sb.toString());sb.delete(0, sb.length());} else {if (timeToken.charAt(i) == ' ' || timeToken.charAt(i) == '\n') {continue;}sb.append(timeToken.charAt(i));}}if (sb.length() >=12) {list.add(sb.toString());}setStartTimeAndEndTime(list);
}private boolean isToken(char ch) {return "-->".contains(String.valueOf(ch));
}private void setStartTimeAndEndTime(List time) {if (time.size() < 2) {throw new RuntimeException("字幕文件不合法!!!");}String startTime = time.get(0);String endTime = time.get(1);int lastIndexOfStartTime = startTime.lastIndexOf(',');int lastIndexOfEndTime = endTime.lastIndexOf(',');String[] startArray = startTime.substring(0, lastIndexOfStartTime).split(":");String[] endArray = endTime.substring(0, lastIndexOfEndTime).split(":");if (startArray.length < 3 || endArray.length < 3) {throw new RuntimeException("字幕文件不合法!!!");}int beginHour = Integer.parseInt(startArray[0]);int beginMintue = Integer.parseInt(startArray[1]);int beginSecond = Integer.parseInt(startArray[2]);int beginMilli = Integer.parseInt(startTime.substring(lastIndexOfStartTime + 1, startTime.length()));int beginTime = (beginHour * 3600 + beginMintue * 60 + beginSecond)* 1000 + beginMilli;srt.setBeginTime(beginTime);int endHour = Integer.parseInt(endArray[0]);int endMintue = Integer.parseInt(endArray[1]);int endSecond = Integer.parseInt(endArray[2]);// 校验时间格式if (!isValid(endMintue, endSecond, beginMintue, beginSecond)) {throw new RuntimeException("时间格式不合法!!!");}int endMilli = Integer.parseInt(endTime.substring(lastIndexOfStartTime + 1, endTime.length()));int endTimeInt = (endHour * 3600 + endMintue * 60 + endSecond )* 1000 + endMilli;srt.setEndTime(endTimeInt);
}

播放功能,需要加上字幕偏移:

public void controller() {// 字幕TreeMap srtMap = solution.getSrtMap();Long startMillSecond = LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli();Set set = srtMap.keySet();int index = 0;SRT srt;while (index < set.size()) {srt = srtMap.get(index);Long nowMillSecond = LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli();Integer beginTime = srt.getBeginTime();Integer endTime = srt.getEndTime();// 加上时间偏移long diff = nowMillSecond - startMillSecond + timeMove.getMilliSecond();if (diff < beginTime) {continue;}String srtBody = srt.getSrtBody();// 更新字幕if (diff >= beginTime && diff <= endTime) {view.setLabel(srtBody);}if (diff <= endTime) {continue;}view.setLabel("");index++;}
}

运行截图展示

 不足之处

        上面是我采用的做法,都是按行读取的,没有按字符去读取解析,读取的解析也做得不是很好,对于一些异常输入没有处理好,还有很多的改进的地方。对于给字幕添加颜色这个功能也没有做出来,鄙人写的比较菜,希望也能给各位带来帮助,如果需要我全部的代码可以在下面评论,也会把代码放到我的资源中(不想花积分下载就私信我就好)。

相关内容

热门资讯

美国不提安卓系统华为,迈向自主... 华为与美国:一场关于技术、市场与政策的较量在当今这个数字化的世界里,智能手机已经成为我们生活中不可或...
安卓系统怎么打开ppt,选择文... 你有没有遇到过这种情况:手里拿着安卓手机,突然需要打开一个PPT文件,却怎么也找不到方法?别急,今天...
谷歌退回到安卓系统,探索创新未... 你知道吗?最近科技圈可是炸开了锅,谷歌竟然宣布要退回到安卓系统!这可不是一个简单的决定,背后肯定有着...
安卓系统待机耗电多少,深度解析... 你有没有发现,手机电量总是不经用?尤其是安卓系统,有时候明明没怎么用,电量就“嗖”的一下子就下去了。...
小米主题安卓原生系统,安卓原生... 亲爱的手机控们,你是否曾为手机界面单调乏味而烦恼?想要给手机换换“衣服”,让它焕然一新?那就得聊聊小...
voyov1安卓系统,探索创新... 你有没有发现,最近你的手机是不是变得越来越流畅了?没错,我要说的就是那个让手机焕发青春的Vivo V...
电脑刷安卓tv系统,轻松打造智... 你有没有想过,家里的安卓电视突然变得卡顿,反应迟钝,是不是时候给它来个“大保健”了?没错,今天就要来...
安卓系统即将要收费,未来手机应... 你知道吗?最近有个大消息在科技圈里炸开了锅,那就是安卓系统可能要开始收费了!这可不是开玩笑的,这可是...
雷凌车载安卓系统,智能出行新体... 你有没有发现,现在的汽车越来越智能了?这不,我最近就体验了一把雷凌车载安卓系统的魅力。它就像一个聪明...
怎样拍照好看安卓系统,轻松拍出... 拍照好看,安卓系统也能轻松搞定!在这个看脸的时代,拍照已经成为每个人生活中不可或缺的一部分。无论是记...
安卓车机系统音频,安卓车机系统... 你有没有发现,现在越来越多的汽车都开始搭载智能车机系统了?这不,咱们就来聊聊安卓车机系统在音频方面的...
老苹果手机安卓系统,兼容与创新... 你手里那台老苹果手机,是不是已经陪你走过了不少风风雨雨?现在,它竟然还能装上安卓系统?这可不是天方夜...
安卓系统7.dns,优化网络连... 你有没有发现,你的安卓手机最近是不是有点儿“慢吞吞”的?别急,别急,让我来给你揭秘这可能与你的安卓系...
安卓手机系统怎么加速,安卓手机... 你有没有发现,你的安卓手机最近变得有点“慢吞吞”的?别急,别急,今天就来给你支几招,让你的安卓手机瞬...
小米note安卓7系统,探索性... 你有没有发现,手机更新换代的速度简直就像坐上了火箭呢?这不,小米Note这款手机,自从升级到了安卓7...
安卓和鸿蒙系统游戏,两大系统游... 你有没有发现,最近手机游戏界可是热闹非凡呢!安卓和鸿蒙系统两大巨头在游戏领域展开了一场激烈的较量。今...
安卓手机没有系统更,揭秘潜在风... 你有没有发现,现在安卓手机的品牌和型号真是五花八门,让人挑花了眼。不过,你知道吗?尽管市面上安卓手机...
充值宝带安卓系统,安卓系统下的... 你有没有发现,最近手机上的一款充值宝APP,在安卓系统上可是火得一塌糊涂呢!这不,今天就来给你好好扒...
安卓系统8.0镜像下载,轻松打... 你有没有想过,想要给你的安卓手机升级到最新的系统,却不知道从哪里下载那个神秘的安卓系统8.0镜像呢?...
安卓系统修改大全,全方位修改大... 你有没有想过,你的安卓手机其实是个大宝藏,里面藏着无数可以让你手机焕然一新的秘密?没错,今天就要来个...