计算行数的最快方法?

时间:2014-06-25 11:55:11

标签: c

计算文件中行号的最简单方法是:

while(!feof(fp))
{
  ch = fgetc(fp);
  if(ch == '\n')
  {
    lines++;
  }
}

但现在的要求是我必须计算大文件中的行数。它会对性能产生影响。

有更好的方法吗?

4 个答案:

答案 0 :(得分:6)

对于速度最快的I / O,您通常希望以文件系统/操作系统的块大小的倍数读/写。

您可以通过调用文件或文件描述符上的statfsfstatfs来查询块大小(阅读手册页)。

struct statfs有一个字段f_bsize,有时也有f_iosize

  

最佳传输块大小

所有POSIX系统AFAIK上都存在f_bsize字段。在Mac OS X和iOS上,还有f_iosize,这是您在这些平台上的首选(但f_bsize也适用于Mac OS X / iOS,通常应该与f_iosize,IIRC相同。

struct statfs fsInfo = {0};
int fd = fileno(fp); // Get file descriptor from FILE*.
long optimalSize;

if (fstatfs(fd, &fsInfo) == -1) {
    // Querying failed! Fall back to a sane value, for example 8kB or 4MB.
    optimalSize = 4 * 1024 * 1024;
} else {
    optimalSize = fsInfo.f_bsize;
}

现在分配该大小的缓冲区并读取(使用readfread)该大小的块。然后迭代这个内存中的块并计算换行数。重复直到EOF。

另一种方法是@Ioan提出的方法:使用mmap将文件映射到内存并迭代该缓冲区。这可能会为您提供最佳性能,因为内核可以以最有效的方式读取数据,但this might fail for files that are "too large"虽然我上面描述的方法始终适用于任意大小的文件,并为您提供接近最佳的性能。

答案 1 :(得分:3)

“有更好的方法吗?”

使用!feof(fp)作为终止条件并不是一个好主意。

你更擅长
while ((ch = fgetc(fp)) != EOF)

检查循环内的新行(如上所述,考虑所有可能的换行符)。

更多信息: http://faq.cprogramming.com/cgi-bin/smartfaq.cgi?answer=1046476070&id=1043284351

答案 2 :(得分:1)

我建议尝试内存映射IO以允许操作系统优化磁盘IO(可能是您最大的瓶颈),而您只需计算行数。还可以考虑一条线可以用4种可能中的任何一种来表示:\ r,\ n,\ r \ n,end-of-file。

答案 3 :(得分:0)

除非文件不包含任何包含行号等元数据的标题,否则查找此数字具有线性复杂性。 还要记住" \ n"不是普遍的换行符。