I\'ve been bumping into a problem. I have a log on a Linux box in which is written the output from several running processes. This file can get really big sometimes and I ne
Would it be possible to optimize this from the other side? If so, just let the logging application always log the line to a file while truncating it (i.e. > instead of >>)
Some optimization might be achieved by "guessing" though, just open the file and with the average log line width you could guess where the last line would be. Jump to that position with fseek and find the last line.
Here is a compilation of the answers here wrapped into a function which can specify how many lines should be returned.
function getLastLines($path, $totalLines) {
$lines = array();
$fp = fopen($path, 'r');
fseek($fp, -1, SEEK_END);
$pos = ftell($fp);
$lastLine = "";
// Loop backword until we have our lines or we reach the start
while($pos > 0 && count($lines) < $totalLines) {
$C = fgetc($fp);
if($C == "\n") {
// skip empty lines
if(trim($lastLine) != "") {
$lines[] = $lastLine;
}
$lastLine = '';
} else {
$lastLine = $C.$lastLine;
}
fseek($fp, $pos--);
}
$lines = array_reverse($lines);
return $lines;
}
This is my solution with only one loop
$line = '';
$f = fopen($file_path, 'r');
$cursor = 0 ;
do {
fseek($f, $cursor--, SEEK_END);
$char = fgetc($f);
$line = $char.$line;
} while (
$cursor > -1 || (
ord($char) !== 10 &&
ord($char) !== 13
)
);
Your problem looks similar to this one
The best approach to avoid loading the whole file into memory seems to be:
$file = escapeshellarg($file); // for the security concious (should be everyone!)
$line = `tail -n 1 $file`;
Untested code from the comments of http://php.net/manual/en/function.fseek.php
jim at lfchosting dot com 05-Nov-2003 02:03
Here is a function that returns the last line of a file. This should be quicker than reading the whole file till you get to the last line. If you want to speed it up a bit, you can set the $pos = some number that is just greater than the line length. The files I was dealing with were various lengths, so this worked for me.
<?php
function readlastline($file)
{
$fp = @fopen($file, "r");
$pos = -1;
$t = " ";
while ($t != "\n") {
fseek($fp, $pos, SEEK_END);
$t = fgetc($fp);
$pos = $pos - 1;
}
$t = fgets($fp);
fclose($fp);
return $t;
}
?>
Use fseek. You seek to the last position and seek it backward (use ftell to tell the current position) until you find a "\n".
$fp = fopen(".....");
fseek($fp, -1, SEEK_END);
$pos = ftell($fp);
$LastLine = "";
// Loop backword util "\n" is found.
while((($C = fgetc($fp)) != "\n") && ($pos > 0)) {
$LastLine = $C.$LastLine;
fseek($fp, $pos--);
}
NOTE: I've not tested. You may need some adjustment.
UPDATE: Thanks Syntax Error
for pointing out about empty file.
:-D
UPDATE2: Fixxed another Syntax Error, missing semicolon at $LastLine = ""