1

Is there a way to show only the last 5 lines of a file with PHP? for instance I have this file:

line1
line2
line3
line4
line5
line6
line7
line8
line9
line10

I want the output to be like this:

line5
line6
line7
line8
line9
line10

NOTE: it's a log file, the line will go on until my program is closed

orlea
  • 547
  • 2
  • 5
  • 13
  • As far as i know - there are no easy and 1-line solution. General approach - open the file, read N last bytes (with `fseek`), analyse them and maybe repeat again - if there are not enough lines. – Ilia Kondrashov Jan 03 '15 at 00:11
  • There's no magic way of doing it.... read each line in turn, pushing to an array, shifting the array if it's more than 5 entries; then the array will only have five entries for the last five lines of the file when you reach EOF – Mark Baker Jan 03 '15 at 00:12
  • 1
    Ugly and dirty - call `tail -n 10` with `system` or `exec` calls. But it's a really edge case. – Ilia Kondrashov Jan 03 '15 at 00:13
  • Already solved guys, please read the answer section – orlea Jan 03 '15 at 00:24
  • @orlea No answer selected, your posted "SOLVED" answer looks a lot Eugen's, and Casey's comment seems like a better solution for large files. – user1032531 Jan 03 '15 at 00:36
  • seems to want a solution for large values of five. – Jasen Jun 30 '17 at 02:38

5 Answers5

2
$text = "line1
line2
line3
line4
line5
line6
line7
line8
line9
line10";
$ex = explode("\n", $text);
$string = "";

for($i = count($ex) - 5; $i <= count($ex); $i++) {
 $string .= $ex[$i]."\n";
}

print $string;
Eugen
  • 1,356
  • 12
  • 15
1

"here's one I prepared earlier"

 $fh=popen("tail -5 ".escapeshellarg($filename),'r');
 echo read($fh);
 pclose($fh);
Jasen
  • 11,837
  • 2
  • 30
  • 48
0

SOLVED

$file = file("/www/wget.log");
for ($i = count($file)-6; $i < count($file); $i++) {
  echo $file[$i] . "\n";
}
orlea
  • 547
  • 2
  • 5
  • 13
0

Not nearly as memory hungry as using file()

$fh = fopen($myFile, 'r');
$lines = array();
while (!feof($fh)) {
    $lines[] = fgets($fh, 999);
    if (count($lines) > 5) {
        array_shift($lines);
    }
}
fclose($fh);
foreach($lines as $line)
    echo $line;

and (just for luck) a version of the same logic that uses SPL

$fh = new SPLFileObject($myFile);
$lines = new SPLQueue();
while (!$fh->eof()) {
    $lines->enqueue($fh->fgets());
    if (count($lines) > 5) {
        $lines->dequeue();
    }
}
while(!$lines->isempty())
    echo $lines->dequeue();
echo '---', PHP_EOL;

which is probably (untested) faster than using arrays because it doesn't have the array_shift() overheads

Mark Baker
  • 209,507
  • 32
  • 346
  • 385
0
$lines=array();
$fp = fopen("file.txt", "r");
while(!feof($fp))
{
   $line = fgets($fp, 4096);
   array_push($lines, $line);
   if (count($lines)>5)
       array_shift($lines);
}
fclose($fp);

--

//how many lines?
$linecount=5;

//what's a typical line length?
$length=40;

//which file?
$file="test.txt";

//we double the offset factor on each iteration
//if our first guess at the file offset doesn't
//yield $linecount lines
$offset_factor=1;


$bytes=filesize($file);

$fp = fopen($file, "r") or die("Can't open $file");


$complete=false;
while (!$complete)
{
    //seek to a position close to end of file
    $offset = $linecount * $length * $offset_factor;
    fseek($fp, -$offset, SEEK_END);


    //we might seek mid-line, so read partial line
    //if our offset means we're reading the whole file, 
    //we don't skip...
    if ($offset<$bytes)
        fgets($fp);

    //read all following lines, store last x
    $lines=array();
    while(!feof($fp))
    {
        $line = fgets($fp);
        array_push($lines, $line);
        if (count($lines)>$linecount)
        {
            array_shift($lines);
            $complete=true;
        }
    }

    //if we read the whole file, we're done, even if we
    //don't have enough lines
    if ($offset>=$bytes)
        $complete=true;
    else
        $offset_factor*=2; //otherwise let's seek even further back

}
fclose($fp);

var_dump($lines);

Source: https://stackoverflow.com/a/2961685/3444315

And useful samples : http://php.net/manual/en/function.fgets.php

Community
  • 1
  • 1
EngineerCoder
  • 1,445
  • 15
  • 30