PHP读取文件的最后几行,而不将整个文件复制到内存中


PHP read last few lines of the file without copying the entire file to memory

你知道我可以使用这个:

<?php
$myfile = 'myfile.txt';
$command = "tac $myfile > /tmp/myfilereversed.txt";
exec($command);
$currentRow = 0;
$numRows = 20;  // stops after this number of rows
$handle = fopen("/tmp/myfilereversed.txt", "r");
while (!feof($handle) && $currentRow <= $numRows) {
   $currentRow++;
   $buffer = fgets($handle, 4096);
   echo $buffer."<br>";
}
fclose($handle);
?>

但它不是把整个文件都复制到内存中吗?

更好的方法可能是fread(),但它使用字节,所以可能也不是一个好方法。

我的文件可以达到100MB左右,所以我想要它。

如果你已经在命令行上做了一些事情,为什么不直接使用tail:

$myfile = 'myfile.txt';
$command = "tail -20 $myfile";
$lines = explode("'n", shell_exec($command));

没有经过测试,但应该可以在PHP不读取整个文件的情况下工作。

尝试应用这个逻辑,因为它可能会有所帮助:以相反的顺序读取长文件fgets

大多数f*()-函数都是基于流的,因此只会读取到内存中,应该读取的内容。

据我所知,你想从文件中读取最后一行$numRows。一个可能幼稚的解决方案

$result = array();
while (!feof($handle)) {
  array_push($result, fgets($handle, 4096));
  if (count($result) > $numRows) array_shift($result);
}

如果你知道(比方说(最大行长度,你可以试着猜测一个位置,它更靠近文件的末尾,但至少在$numRows之前,即的末尾

$seek = $maxLineLength * ($numRows + 5); // +5 to assure, we are not too far
fseek($handle, -$seek, SEEK_END);
// See code above