如何使用Objective-C从大文本文件中读取特定行?

时间:2012-08-09 00:03:47

标签: objective-c ios cocoa-touch

说我有像这样的文本文件my.txt

this is line 1
this is line 2
....
this is line 999999
this is line 1000000

在Unix中,我可以通过发出“head -1000 my.txt | tail -1”之类的命令获得“this is line 1000”的行。在Objective-C中获得此功能的相应方法是什么?

4 个答案:

答案 0 :(得分:3)

如果将整个事物同时存储在内存中并不是太低效,那么最紧凑的调用序列(我已经扩展到多行以便简化说明)将是:

NSError *error = nil;
NSString *sourceString = [NSString stringWithContentsOfFile:@"..."
                                    encoding:NSUTF8StringEncoding error:&error];
NSArray *lines = [sourceString componentsSeparatedByCharactersInSet:
                                     [NSCharacterSet newlineCharacterSet]];

NSString *relevantLine = [lines objectAtIndex:1000];

您应该检查error的值和count的{​​{1}}进行验证。

编辑:为了与Nathan的答案进行比较,在集合中按字符分割的好处是你可以接受任何可能划分换行符的五个unicode字符,其中几个字符串彼此相邻只计算一次休息(例如lines)。

\r\n可能是你需要处理的内容,如果内存占用是一个问题,它几乎没有比C的stdio.h fopen / fread / etc更进化,所以你将不得不写下你自己的小循环来突破。

答案 1 :(得分:2)

答案并未解释如何读取文件 LARGE 以保留在内存中。 Objective-C中没有很好的解决方案来读取大文本文件而不将它们放入内存(这不是一个选项)。

在这些情况下,我喜欢使用c方法:

FILE* file = fopen("path to my file", "r");

size_t length;
char *cLine = fgetln(file,&length);

while (length>0) {
    char str[length+1];
    strncpy(str, cLine, length);
    str[length] = '\0';

    NSString *line = [NSString stringWithFormat:@"%s",str];        
    % Do what you want here.

    cLine = fgetln(file,&length);
}

请注意,fgetln不会保留换行符。另外,我们+1为str​​的长度,因为我们想为NULL终止腾出空间。

答案 2 :(得分:1)

最简单的方法是使用一个NSString文件方法加载文件,然后使用 - [NSString componentsSeparatedByString:]方法获取每一行的数组。

或者您可以使用NSScanner,扫描新行/回车字符,直到您到达感兴趣的行。

如果您真的关心内存使用情况,可以查看NSInputStream使用它来读取文件,保留新行数。令人遗憾的是,NSScanner无法使用NSInputStream。

答案 3 :(得分:1)

我不认为这是完全重复的,因为听起来你想跳过文件中的某些行,但是你可以轻松地使用像这样的方法:

Objective-C: Reading a file line by lineSpecific answer有一些示例代码)

循环输入文件,读入一大块数据,并查找换行符。计算它们,当你找到正确的数字时,输出数据后直到下一个数据。

您的示例看起来可能有数十万行,所以绝对不要只是将文件读入NSString,并且绝对不会将其转换为NSArray。

如果你想以更高级的NSInputStream方式(在字符集解码中具有一些关键优势)这样做,这里有一个很好的例子,它显示了轮询使用来自流源的所有数据的基本思想(在文件示例,它有点矫枉过正)。它用于输出,但输入的想法也很好: Polling versus Run Loop Scheduling