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

时间:2011-07-01 18:20:45

标签: php

嗯,你知道我可以用这个:

<?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,所以我想要它。

3 个答案:

答案 0 :(得分:2)

如果您已在命令行上执行操作,为什么不直接使用tail

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

未经过测试,但无需PHP就必须阅读整个文件。

答案 1 :(得分:0)

尝试应用此逻辑,因为它可能有所帮助:read long file in reverse order fgets

答案 2 :(得分:0)

大多数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