PHP - Returning the Last Line in a File

PHP - Returning the last line in a file?

The simplest naive solution is simply:

$file = "/path/to/file";
$data = file($file);
$line = $data[count($data)-1];

Though, this WILL load the whole file into memory. Possibly a problem (or not). A better solution is this:

$file = escapeshellarg($file); // for the security concious (should be everyone!)
$line = `tail -n 1 $file`;

Read last line from file

This should work:

$line = '';

$f = fopen('data.txt', 'r');
$cursor = -1;

fseek($f, $cursor, SEEK_END);
$char = fgetc($f);

/**
* Trim trailing newline chars of the file
*/
while ($char === "\n" || $char === "\r") {
fseek($f, $cursor--, SEEK_END);
$char = fgetc($f);
}

/**
* Read until the start of file or first newline char
*/
while ($char !== false && $char !== "\n" && $char !== "\r") {
/**
* Prepend the new char
*/
$line = $char . $line;
fseek($f, $cursor--, SEEK_END);
$char = fgetc($f);
}

fclose($f);

echo $line;

Note that this solution will repeat the last character of the line unless your file ends in a newline. If your file does not end in a newline, you can change both instances of $cursor-- to --$cursor.

Extract data from last line in a text file using PHP

It's normally done with a one-liner if the file is not too large, or close to one:

vprintf(
'Rainfall prediced now: %4$smm'
, explode(' ', end((
file($path, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES)
)))
);

If the input format is more complex, also use sscanf or preg_match to parse the last line.

Edit As you write the file is small, you can also load it into a string (file_get_contents) and parse that string from behind:

$buffer = '#date #time  #blah #rainfall  #blah   #blah
200813 1234 1234 0.5 1234 1234
200813 1235 1234 1.2 1234 1234
200813 1236 1234 3.5 1234 1234
200813 1237 1234 0.2 1234 1234
200813 1238 1234 0.1 1234 1234';

preg_match('/([^ ]+)\s+\d+\s+\d+\R?$/', $buffer, $matches)
&& vprintf('Rainfall prediced now: %2$smm', $matches);

// prints "Rainfall prediced now: 0.1mm"

What is the best way to read last lines (i.e. tail) from a file using PHP?

Methods overview

Searching on the internet, I came across different solutions. I can group them
in three approaches:

  • naive ones that use file() PHP function;
  • cheating ones that runs tail command on the system;
  • mighty ones that happily jump around an opened file using fseek().

I ended up choosing (or writing) five solutions, a naive one, a cheating one
and three mighty ones.

  1. The most concise naive solution,
    using built-in array functions.
  2. The only possible solution based on tail command, which has
    a little big problem: it does not run if tail is not available, i.e. on
    non-Unix (Windows) or on restricted environments that don't allow system
    functions.
  3. The solution in which single bytes are read from the end of file searching
    for (and counting) new-line characters, found here.
  4. The multi-byte buffered solution optimized for large files, found
    here.
  5. A slightly modified version of solution #4 in which buffer length is
    dynamic, decided according to the number of lines to retrieve.

All solutions work. In the sense that they return the expected result from
any file and for any number of lines we ask for (except for solution #1, that can
break PHP memory limits in case of large files, returning nothing). But which one
is better?

Performance tests

To answer the question I run tests. That's how these thing are done, isn't it?

I prepared a sample 100 KB file joining together different files found in
my /var/log directory. Then I wrote a PHP script that uses each one of the
five solutions to retrieve 1, 2, .., 10, 20, ... 100, 200, ..., 1000 lines
from the end of the file. Each single test is repeated ten times (that's
something like 5 × 28 × 10 = 1400 tests), measuring average elapsed
time
in microseconds.

I run the script on my local development machine (Xubuntu 12.04,
PHP 5.3.10, 2.70 GHz dual core CPU, 2 GB RAM) using the PHP command line
interpreter. Here are the results:

Execution time on sample 100 KB log file

Solution #1 and #2 seem to be the worse ones. Solution #3 is good only when we need to
read a few lines. Solutions #4 and #5 seem to be the best ones.
Note how dynamic buffer size can optimize the algorithm: execution time is a little
smaller for few lines, because of the reduced buffer.

Let's try with a bigger file. What if we have to read a 10 MB log file?

Execution time on sample 10 MB log file

Now solution #1 is by far the worse one: in fact, loading the whole 10 MB file
into memory is not a great idea. I run the tests also on 1MB and 100MB file,
and it's practically the same situation.

And for tiny log files? That's the graph for a 10 KB file:

Execution time on sample 10 KB log file

Solution #1 is the best one now! Loading a 10 KB into memory isn't a big deal
for PHP. Also #4 and #5 performs good. However this is an edge case: a 10 KB log
means something like 150/200 lines...

You can download all my test files, sources and results
here.

Final thoughts

Solution #5 is heavily recommended for the general use case: works great
with every file size and performs particularly good when reading a few lines.

Avoid solution #1 if you
should read files bigger than 10 KB.

Solution #2
and #3
aren't the best ones for each test I run: #2 never runs in less than
2ms, and #3 is heavily influenced by the number of
lines you ask (works quite good only with 1 or 2 lines).

How to read only 5 last line of the text file in PHP?

Untested code, but should work:

$file = file("filename.txt");
for ($i = max(0, count($file)-6); $i < count($file); $i++) {
echo $file[$i] . "\n";
}

Calling max will handle the file being less than 6 lines.

PHP: Retrieving lines from the end of a large text file

If you are on a 'nix machine, you should be able to use shell escaping and the tool 'tail'.
It's been a while, but something like this:

$lastLines = `tail -n 500`;

notice the use of tick marks, which executes the string in BASH or similar and returns the results.

How can I skip the first and the last line of a file in PHP

You could read the lines in an array first with file and then perform the removal with array_slice:

function get_file_tail($filepath){
// Read file as lines into an array
$lines = file($filepath);
// Remove first and last line
$lines = array_slice($lines, 1, count($lines)-2);
// Convert to string (if array is not useful for you) and return it
return implode(PHP_EOL, $lines);
}

Example call:

echo get_file_tail("http://websitetips.com/articles/copy/lorem/ipsum.txt");

PHP Grab last 15 lines in txt file

Try using array_slice, which will return a part of an array. In this case you want it to return the last 15 lines of the array, so:

$filearray = file("filename");
$lastfifteenlines = array_slice($filearray,-15);

php system() does not return the last line of output

The last line is an error and gets written to STDERR and not STDOUT. You need to redirect the STDERR to STDOUT if you want to get errors with PHP, you can do that by adding 2>&1 at the end of your command.



Related Topics



Leave a reply



Submit