Usar um loop de fgets()
chamadas é a solução perfeita e a mais direta de escrever, no entanto:
mesmo que internamente o arquivo seja lido usando um buffer de 8.192 bytes, seu código ainda precisa chamar essa função para cada linha.
é tecnicamente possível que uma única linha seja maior do que a memória disponível se você estiver lendo um arquivo binário.
Este código lê um arquivo em blocos de 8kB cada e conta o número de novas linhas dentro desse bloco.
function getLines($file)
{
$f = fopen($file, 'rb');
$lines = 0;
while (!feof($f)) {
$lines += substr_count(fread($f, 8192), "\n");
}
fclose($f);
return $lines;
}
Se o comprimento médio de cada linha for no máximo 4kB, você já começará a economizar nas chamadas de função, que podem aumentar ao processar arquivos grandes.
Benchmark
Fiz um teste com um arquivo de 1 GB; aqui estão os resultados:
+-------------+------------------+---------+
| This answer | Dominic's answer | wc -l |
+------------+-------------+------------------+---------+
| Lines | 3550388 | 3550389 | 3550388 |
+------------+-------------+------------------+---------+
| Runtime | 1.055 | 4.297 | 0.587 |
+------------+-------------+------------------+---------+
O tempo é medido em segundos em tempo real, veja aqui o que significa real
\n
) sendo analisado em uma máquina Windows (PHP_EOL == '\r\n'
)