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
  • 184,866
  • 48
  • 414
  • 792
kritya
  • 3,242
  • 6
  • 41
  • 59

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
  • 119,594
  • 33
  • 182
  • 182
0

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

AlienWebguy
  • 75,484
  • 17
  • 116
  • 141
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
  • 124,572
  • 19
  • 146
  • 171