Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Parsing SRT file with Objective C

Text example:

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

In JavaScript I would parse this with a regular expression certainly. I'm just wondering, is that the best way to do this in Obj C? I'm sure I could figure out a way to do this, but I'm wanting to do it an appropriate way.

I only need to know where to start and I'm happy to do the rest, but for understanding sake I'm going to end up with something like this (pseudo code):

NSDictionary
index -> [0-9]+
start -> hh:mm:ss,mmm
end -> hh:mm:ss,mmm
text -> one of the lines of text

In this case, I'd be parsing three entries into my dictionary.

like image 295
Jacksonkr Avatar asked Jan 11 '13 22:01

Jacksonkr


1 Answers

Some background: I wrote a small app and created a file called stuff.srt containing your examples that resides in the bundle; hence, my means of accessing it.

This is just a quick and dirty thing, a proof-of-concept. Note that it doesn't check results. Real applications always check their results. As you can see, the work takes place in the -applicationDidFinishLaunching: method (I'm working in Mac OS X, not iOS).

EDIT:

It's been pointed out that the code as originally posted didn't handle multiple text lines correctly. To address this, I take advantage of the fact that SRT files use CRLF as their line breaks, and search for two occurrences of this sequence. I then change all occurrences of CRLF in the text string to spaces, based on what I observed here. This doesn't account for leading or trailing spaces in each line of the text.

I changed the contents of the stuff.srt file to this:

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

and the code has been revised as follows (I also put everything into an @autoreleasepool directive; there might be a lot of autoreleased objects generated in the course of parsing the file!):

- (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);
        }
    }
}

The revised output looks like this:

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";
}

One other thing I learned from what I've read today: The SRT file format originated in France, and the comma seen in the input is the decimal separator used there.

like image 87
Extra Savoir-Faire Avatar answered Oct 25 '22 05:10

Extra Savoir-Faire