2013-01-11 30 views
5

chữ ví dụ:tập tin Parsing SRT với Objective C

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 

Trong JavaScript tôi sẽ phân tích này với một biểu thức chính quy chắc chắn. Tôi chỉ tự hỏi, đó là cách tốt nhất để làm điều này trong Obj C? Tôi chắc rằng tôi có thể tìm ra cách cách để thực hiện việc này, nhưng tôi muốn thực hiện theo cách thích hợp.

Tôi chỉ cần biết bắt đầu từ đâu và tôi rất vui khi được làm phần còn lại, nhưng để hiểu được vì tôi sẽ kết thúc với một cái gì đó như thế này (pseudo code):

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

Trong trường hợp này, tôi sẽ phân tích ba mục nhập vào từ điển của tôi.

+1

Bằng cách tốt nhất bạn có nghĩa là hiệu quả hoặc dễ làm? –

+0

Tôi sai về mặt hiệu quả, nhưng tôi sẽ lấy bất kỳ sự trợ giúp nào mà tôi có thể nhận được và chỉ ghép chúng lại với nhau theo cách tôi thấy tốt nhất. – Jacksonkr

+0

Ok nó khá rõ ràng, điều duy nhất tôi không hiểu là những gì bạn có ý nghĩa cho "mmm", là những mili giây? –

Trả lời

11

Một số nền: Tôi đã viết một ứng dụng nhỏ và tạo một tệp có tên stuff.srt chứa các ví dụ của bạn nằm trong gói; do đó, phương tiện của tôi truy cập nó.

Đây chỉ là một điều nhanh chóng và bẩn thỉu, một bằng chứng về khái niệm. Lưu ý rằng nó không kiểm tra kết quả. Các ứng dụng thực tế luôn kiểm tra kết quả của chúng. Như bạn có thể thấy, công việc diễn ra theo phương pháp -applicationDidFinishLaunching: (Tôi đang làm việc trong Mac OS X chứ không phải iOS).

EDIT:

Nó được chỉ ra rằng các mã như ban đầu được đăng không xử lý nhiều dòng văn bản một cách chính xác. Để giải quyết vấn đề này, tôi tận dụng thực tế là SRT files use CRLF as their line breaks và tìm kiếm hai lần xuất hiện của chuỗi này. Sau đó tôi thay đổi tất cả các lần xuất hiện của CRLF trong chuỗi văn bản thành dấu cách, dựa trên những gì tôi quan sát được here. Điều này không tính đến các khoảng trắng đầu hoặc cuối trong mỗi dòng văn bản.

Tôi đã thay đổi nội dung của file stuff.srt này:

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 

và mã đã được sửa đổi như sau (tôi cũng đưa mọi thứ vào một chỉ thị @autoreleasepool; có thể có rất nhiều của các đối tượng autoreleased tạo ra trong quá trình phân tích các tập tin):

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

sản lượng sửa đổi như sau:

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

Một điều khác tôi đã học được từ những gì tôi đã đọc hôm nay: Định dạng tệp SRT có nguồn gốc ở Pháp và dấu phẩy được thấy trong đầu vào là dấu phân cách thập phân được sử dụng ở đó.

+0

Tôi sẽ thực hiện một triển khai rất gần với bạn vì vậy tôi hình tôi sẽ cung cấp cho bạn điểm và chỉ cần đưa giải pháp cá nhân của tôi vào một chỉnh sửa cho câu hỏi của tôi. Cảm ơn bạn đã giúp đỡ! – Jacksonkr

+0

Bạn được chào đón! – trudyscousin

+0

Cảm ơn, điều này rất hữu ích đối với tôi, nhưng tôi nhận thấy có sự cố về các văn bản có nhiều dòng. Trong trường hợp đó việc phân tích cú pháp bị hỏng. –

0

Đề xuất của tôi là sử dụng NSDateFormatter để phân tích cú pháp dòng thứ hai. Tôi sẽ chia chuỗi đó thành hai chuỗi (xem componentsSeparatedByString: trong NSString class reference). Điều này trong khi đọc dòng tệp trên mỗi dòng.

Vì vậy, vòng lặp sẽ là:

  • Nếu tập tin chứa lại dữ liệu, đọc dòng tiếp theo;
  • Nếu dòng tiếp theo là bội số của 4, hãy cấp phát một đối tượng mới.Đối tượng này sẽ có thể chứa hai ngày, một số nguyên và một chuỗi;
  • Nếu dòng tiếp theo không phải là bội số của 4, hãy đọc dòng và gán giá trị của nó cho trường tương ứng.