2

考虑到我有一个包含数百万行文本的 100GB txt 文件。我如何使用 PHP 逐行读取这个文本文件?

我无法使用 file_get_contents();,因为文件太大。fgets() 还逐行阅读文本,这可能需要更长的时间才能完成整个文件的阅读。

如果我将使用fread($fp,5030)其中“5030”是它必须读取的某个长度值。会不会因为已经达到最大长度而无法读取整行(例如停在行的中间)?

4

5 回答 5

4

我不能使用 file_get_contents(); 因为文件太大。fgets() 还逐行读取文本,这可能需要更长的时间才能完成整个文件的读取。

不明白,为什么你不能使用fgets()

$blocksize = 50; // in "number of lines"
while (!feof($fh)) {
  $lines = array();
  $count = 0;
  while (!feof($fh) && (++$count <= $blocksize)) {
    $lines[] = fgets($fh);
  }
  doSomethingWithLines($lines);
}

无论如何,读取 100GB 都需要时间。

于 2011-07-18T13:03:25.127 回答
1

这种fread方法听起来像是一个合理的解决方案。您可以通过检查字符串中的最后一个字符是否为换行符 ( '\n') 来检测是否已到达行尾。如果不是,那么您可以读取更多字符并将它们附加到现有字符串中,或​​者您可以将字符串中的字符修剪回最后一个换行符,然后用于fseek调整您在文件中的位置。

旁白:您是否知道读取 100GB 的文件需要长时间?

于 2011-07-18T13:02:29.527 回答
1

我认为你必须使用 fread($fp, somesize),并手动检查你是否已经建立了行尾,否则读取另一个块。

希望这可以帮助。

于 2011-07-18T13:03:13.340 回答
1

我建议在函数中实现单行的读取,从代码的其余部分隐藏该特定步骤的实现细节 - 处理函数必须不关心如何检索该行。然后,您可以使用实现您的第一个版本fgets(),然后如果您发现它太慢,请尝试其他方法。很可能是最初的实现太慢了,但关键是:在你进行基准测试之前你不会知道。

于 2011-07-18T13:03:14.580 回答
0

我知道这是一个老问题,但我认为对于最终找到这个问题的任何人来说,一个新的答案是有价值的。

我同意阅读 100GB 需要时间,这就是为什么我也同意我们需要找到最有效的选择来阅读它,这样它就可以尽可能少,而不是仅仅想“如果已经很多了,谁在乎它有多少“所以,让我们找出我们可能的最短时间。

另一种解决方案:

缓存一大块原始数据

使用 fread 读取该数据的缓存

逐行阅读

从缓存中逐行读取,直到缓存结束或找到数据结束

阅读下一个块并重复

抓取块中未处理的最后一部分(您正在寻找行分隔符的部分)并将其移动到前面,然后读取您定义的大小减去未处理数据的大小并将其放在后面未处理的块,然后,你去,你有一个新的完整块。
重复逐行读取和此过程,直到文件被完全读取。

您应该使用大于任何预期行大小的缓存块。

缓存大小越大,读取速度越快,但使用的内存越多。

于 2016-12-02T14:10:41.843 回答