4

假设我有这样的文本文件 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”之类的命令来获得“这是第 1000 行”的行。在 Objective-C 中得到这个的相应方法是什么?

4

4 回答 4

3

如果一次将整个内容存储在内存中并不是太低效,那么最紧凑的调用序列(为了更简单的说明,我已经扩展为多行)将是:

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

NSString *relevantLine = [lines objectAtIndex:1000];

您应该检查 oferrorcountof的值以lines进行验证。

编辑:与 Nathan 的回答相比,按集合中的字符拆分的好处是,您将接受可能分隔换行符的五个 unicode 字符中的任何一个,其中几个字符彼此相邻的任何地方都算作仅一次休息(根据例如\r\n)。

NSInputStream如果内存占用是一个问题,这可能是您必须处理的问题,它几乎不比 C 的 stdio.h fopen/fread/etc 进化,所以您将不得不编写自己的小循环来冲刺.

于 2012-08-09T00:23:34.207 回答
2

答案没有解释如何读取太大而无法保存在内存中的文件。在 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 不会保留您的换行符。此外,我们将 str 的长度 +1,因为我们想为 NULL 终止腾出空间。

于 2016-03-07T19:48:26.763 回答
1

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

Objective-C:逐行读取文件 (有一些示例代码的具体答案)

循环输入文件,读入一大块数据,然后寻找换行符。数一数,当你打到正确的数字时,输出那个之后的数据,直到下一个。

您的示例看起来可能有数十万行,因此绝对不要只将文件读入 NSString,也绝对不要将其转换为 NSArray。

如果您想使用更高级的 NSInputStream 方式(在字符集解码方面具有一些关键优势),这里有一个很好的示例,它展示了轮询以使用来自流源的所有数据的基本思想(在文件示例中,它有点矫枉过正)。它用于输出,但这个想法也适用于输入: 轮询与运行循环调度

于 2012-08-09T00:37:22.097 回答
1

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

或者您可以使用 NSScanner,扫描换行符/回车符,对它们进行计数,直到找到您感兴趣的行。

如果您真的担心内存使用情况,您可以查看 NSInputStream 使用它来读取文件,并计算换行符的数量。很遗憾 NSScanner 不能与 NSInputStream 一起使用。

于 2012-08-09T00:22:40.567 回答