在 PHP 中,我使用 fopen( )
、fgets( )
和 fclose( )
逐行读取文件。它运作良好。但是我有一个脚本(从 CLI 运行)必须处理三百个 5GB 的文本文件。这大约是 30 亿个 fgets( )
。所以它工作得很好,但在这种规模下,微小的速度节省将以极快的速度累积起来。所以我想知道是否有任何技巧可以加快这个过程?
我想到的唯一可能的事情是让 fgets( )
一次读取多行。它看起来并不支持,但理论上我可以说 20 个连续的 $line[] = fgets($file);
然后处理数组。这与在一个命令中读取多行并不完全相同,因此它可能没有任何影响。但我知道将您的 mysql 插入排队并将它们作为一个巨大的插入发送(我将在更多测试和基准测试后在此脚本中实现的另一个技巧)将节省大量时间。
2019 年 4 月 13 日更新 这是我使用的解决方案。最初我有一个更复杂的方法来切掉每次阅读的结尾,但后来我意识到你可以做得更简单。
$index_file = fopen( path to file,"r" );
$chunk = "";
while ( !feof($index_file) )
{
$chunk .= fread($index_file,$read_length);
$payload_lines = explode("\n",$chunk);
if ( !feof($index_file) )
{ $chunk = array_pop($payload_lines); }
}
当然,PHP 具有适用于一切的函数。因此,我将每次读取都分解为一个行数组,并将数组中的最后一项 array_pop()
返回到“读取缓冲区”的开头。最后一部分可能是 split 的,但不一定是 split 的。但无论哪种方式,它都会返回并在下一个循环中进行处理(除非我们处理完文件,否则我们不会弹出它)。
在这里您唯一需要注意的是,如果您的一行太长以至于单次读取无法捕获全部内容。但是了解您的数据,这可能不会很麻烦。对我来说,我正在解析一个 json-ish 文件,我一次读取 128 KB,所以在我的读取中总是有很多换行符。
注意:我通过进行一百万次基准测试并发现我的服务器处理速度绝对最快,最终确定为 128 KB。此解析函数将运行 300 次,因此我每节省一秒,总运行时间就会节省 5 分钟。
最佳答案
一种可能更快的方法是使用 fread()
读取文件的大块,用换行符拆分它,然后处理这些行。您必须考虑到这些 block 可能会切断线条,您必须检测到这一点并将它们粘在一起。
一般来说,您一次可以读取的数据 block 越大,您的进程就应该变得越快。在可用内存的限制内。
来自 fread()
docs :
Note that fread() reads from the current position of the file pointer. Use ftell() to find the current position of the pointer and rewind() to rewind the pointer position.
关于php - 逐行读取文件的更快方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44281401/