1

Well you know I can use this:

<?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);
?>

But doesn't it copy the whole file to memory?

A better approach maybe fread() but it uses the bytes so might also not be the a good approach too.

My file can go into around 100MB so I want it.

hakre
  • 193,403
  • 52
  • 435
  • 836
kritya
  • 3,312
  • 7
  • 43
  • 60

3 Answers3

2

If you're already doing stuff on the command line, why not use tail directly:

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

Not tested, but should work without PHP having to read the whole file.

Tatu Ulmanen
  • 123,288
  • 34
  • 187
  • 185
0

Try applying this logic as it might help: read long file in reverse order fgets

AlienWebguy
  • 76,997
  • 17
  • 122
  • 145
0

Most f*()-functions are stream-based and therefore will only read into memory, what should get read.

As fas as I understand you want to read the last $numRows line from a file. A maybe naive solution

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

If you know (lets say) the maximum line length, you can try to guess a position, that is nearer at the end of the file, but before at least $numRows the end

$seek = $maxLineLength * ($numRows + 5); // +5 to assure, we are not too far
fseek($handle, -$seek, SEEK_END);
// See code above
KingCrunch
  • 128,817
  • 21
  • 151
  • 173