kritya
kritya

Reputation: 3362

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

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.

Upvotes: 1

Views: 1636

Answers (3)

KingCrunch
KingCrunch

Reputation: 131841

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

Upvotes: 0

SeanCannon
SeanCannon

Reputation: 77956

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

Upvotes: 0

Tatu Ulmanen
Tatu Ulmanen

Reputation: 124768

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.

Upvotes: 2

Related Questions