但是,使用 fgets()
调用循环是很好的解决方案,也是最直接的编写方法:
-
即使在内部使用 8192 字节的缓冲区读取文件,您的代码仍然必须为每行调用该函数。
-
从技术上讲,如果您正在读取二进制文件,则单个行可能大于可用内存。
此代码以每个 8kB 的块读取文件,然后计算该块中的换行符数。
function getLines($file)
{
$f = fopen($file, 'rb');
$lines = 0;
while (!feof($f)) {
$lines += substr_count(fread($f, 8192), "\n");
}
fclose($f);
return $lines;
}
如果每行的平均长度最多为4kB,则您已经开始保存函数调用,并且在处理大文件时这些长度可能会增加。
基准
我用一个1GB的文件运行了一个测试;以下是结果:
+-------------+------------------+---------+
| This answer | Dominic's answer | wc -l |
+------------+-------------+------------------+---------+
| Lines | 3550388 | 3550389 | 3550388 |
+------------+-------------+------------------+---------+
| Runtime | 1.055 | 4.297 | 0.587 |
+------------+-------------+------------------+---------+
时间以秒为单位实时测量,在这里看看真正的意味着什么
真实行数
虽然上述方法运行良好,并且返回的结果与 相同,但如果文件结尾没有换行符,则行号将偏离一个;如果您关心此特定方案,则可以使用以下逻辑使其更准确:wc -l
function getLines($file)
{
$f = fopen($file, 'rb');
$lines = 0; $buffer = '';
while (!feof($f)) {
$buffer = fread($f, 8192);
$lines += substr_count($buffer, "\n");
}
fclose($f);
if (strlen($buffer) > 0 && $buffer[-1] != "\n") {
++$lines;
}
return $lines;
}