使用 Objective C 解析 SRT 文件
Posted
技术标签:
【中文标题】使用 Objective C 解析 SRT 文件【英文标题】:Parsing SRT file with Objective C 【发布时间】:2013-01-11 22:12:45 【问题描述】:文字示例:
1
00:00:00,000 --> 00:00:01,000
This is the first line
2
00:00:01,000 --> 00:00:02,000
This is the second line
3
00:00:02,000 --> 00:00:03,000
This is the last line
在 javascript 中,我当然会使用正则表达式来解析它。我只是想知道,这是在 Obj C 中执行此操作的最佳方法吗?我确信我可以找到一种方式来做到这一点,但我想以一种适当的方式来做到这一点。
我只需要知道从哪里开始,剩下的事情我很乐意做,但为了理解起见,我最终会得到这样的东西(伪代码):
NSDictionary
index -> [0-9]+
start -> hh:mm:ss,mmm
end -> hh:mm:ss,mmm
text -> one of the lines of text
在这种情况下,我会将三个条目解析到我的字典中。
【问题讨论】:
最好的方式是指高效或易行? 我在效率方面犯了错误,但我会尽我所能得到的帮助,并以我认为最好的方式拼凑起来。 好吧,很清楚,我唯一不明白的是你的“mmm”是什么意思,这些是毫秒吗? @RamyAlZuhouri 是的。我做了 mmm 毫秒。 【参考方案1】:一些背景知识:我编写了一个小应用程序并创建了一个名为 stuff.srt 的文件,其中包含驻留在包中的示例;因此,我的访问方式。
这只是一个快速而肮脏的事情,一个概念验证。请注意,它不检查结果。实际应用程序总是检查他们的结果。如您所见,工作发生在 -applicationDidFinishLaunching:
方法中(我在 Mac OS X 中工作,而不是 ios)。
编辑:
有人指出,最初发布的代码没有正确处理多个文本行。为了解决这个问题,我利用SRT files use CRLF as their line breaks 的事实,并搜索此序列的两次出现。然后,根据我观察到的here,我将文本字符串中所有出现的 CRLF 更改为空格。这不考虑文本每行中的前导或尾随空格。
我将 stuff.srt 文件的内容更改为:
1
00:00:00,000 --> 00:00:01,000
This is the first line
and it has a secondary line
2
00:00:01,000 --> 00:00:02,000
This is the second line
3
00:00:02,000 --> 00:00:03,000
This is the last line
and it has a secondary line too
并且代码已修改如下(我还将所有内容都放入了@autoreleasepool 指令;在解析文件的过程中可能会生成很多个自动释放的对象!):
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
NSString *path = [[NSBundle mainBundle] pathForResource:@"stuff" ofType:@"srt"];
NSString *string = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:NULL];
NSScanner *scanner = [NSScanner scannerWithString:string];
while (![scanner isAtEnd])
@autoreleasepool
NSString *indexString;
(void) [scanner scanUpToCharactersFromSet:[NSCharacterSet newlineCharacterSet] intoString:&indexString];
NSString *startString;
(void) [scanner scanUpToString:@" --> " intoString:&startString];
// My string constant doesn't begin with spaces because scanners
// skip spaces and newlines by default.
(void) [scanner scanString:@"-->" intoString:NULL];
NSString *endString;
(void) [scanner scanUpToCharactersFromSet:[NSCharacterSet newlineCharacterSet] intoString:&endString];
NSString *textString;
// (void) [scanner scanUpToCharactersFromSet:[NSCharacterSet newlineCharacterSet] intoString:&textString];
// BEGIN EDIT
(void) [scanner scanUpToString:@"\r\n\r\n" intoString:&textString];
textString = [textString stringByReplacingOccurrencesOfString:@"\r\n" withString:@" "];
// Addresses trailing space added if CRLF is on a line by itself at the end of the SRT file
textString = [textString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
// END EDIT
NSDictionary *dictionary = [NSDictionary dictionaryWithObjectsAndKeys:
indexString, @"index",
startString, @"start",
endString , @"end",
textString , @"text",
nil];
NSLog(@"%@", dictionary);
修改后的输出如下所示:
2013-02-09 16:10:17.727 SRTFileScan[4846:303]
end = "00:00:01,000";
index = 1;
start = "00:00:00,000";
text = "This is the first line and it has a secondary line";
2013-02-09 16:10:17.729 SRTFileScan[4846:303]
end = "00:00:02,000";
index = 2;
start = "00:00:01,000";
text = "This is the second line";
2013-02-09 16:10:17.730 SRTFileScan[4846:303]
end = "00:00:03,000";
index = 3;
start = "00:00:02,000";
text = "This is the last line and it has a secondary line too";
我从今天阅读的内容中学到的另一件事:SRT 文件格式起源于法国,输入中看到的逗号是那里使用的小数分隔符。
【讨论】:
我将做一个非常接近你的实现,所以我想我会告诉你重点,只是将我的个人解决方案放入我的问题的编辑中。感谢您的帮助! 谢谢,这对我很有用,但我注意到多行文本存在问题。在这种情况下,解析被破坏。 嗨,感谢您现在支持多行,在我的文件中我想我只有 \n 所以可能我使用的是非标准 .srt (使用的换行符通常是 CR+LF 对)。然后我建议保留“\n”而不是保留多行的空间。 @EmanueleFumagalli 这是我必须注意的事情;我最初使用 OP 提供的数据创建了自己的文件,我没有注意使用的换行符类型。无论如何,不客气,谢谢。 @CraigGrummitt 这个我自己没试过,但是:先记录下扫描仪的当前位置。然后,扫描 \r\n\r\n。如果这导致scanner.isAtEnd == YES,则使用保存的位置恢复扫描仪的位置,然后扫描\n\n。【参考方案2】:Apple 有一个解析字幕文件的示例代码。在此处查看相关部分:
https://developer.apple.com/library/mac/samplecode/avsubtitleswriterOSX/Listings/avsubtitleswriter_SubtitlesTextReader_m.html#//apple_ref/doc/uid/DTS40013409-avsubtitleswriter_SubtitlesTextReader_m-DontLinkElementID_5
【讨论】:
【参考方案3】:我的建议是使用NSDateFormatter 来解析第二行。我会将该字符串拆分为两个字符串(请参阅 componentsSeparatedByString: in NSString class reference)。这在每行读取文件行时。
所以循环是:
如果文件再次包含数据,则读取下一行; 如果下一行是 4 的倍数,则分配一个新对象。这个对象应该可以包含两个日期,一个整数和一个字符串; 如果下一行不是 4 的倍数,则读取该行并将其值分配给相应的字段。【讨论】:
以上是关于使用 Objective C 解析 SRT 文件的主要内容,如果未能解决你的问题,请参考以下文章