Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Read last line from file

Tags:

file

php

file-io

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 need to read the last line from that file.

The problem is this action will be called via an AJAX request pretty often and when the file size of that log gets over 5-6MB it's rather not good for the server. So I'm thinking I have to read the last line but not to read the whole file and pass through it or load it in RAM because that would just load to death my box.

Is there any optimization for this operation so that it run smooth and not harm the server or kill Apache?

Other option that I have is to exec('tail -n 1 /path/to/log') but it doesn't sound so good.

Later edit: I DO NOT want to put the file in RAM because it might get huge. fopen() is not an option.

like image 717
Bogdan Constantinescu Avatar asked Oct 02 '09 15:10

Bogdan Constantinescu


People also ask

How do I read the last line of a text file?

var lastLine = File. ReadLines("file. txt"). Last();

How do I print the last line of a file?

Find out the last line of a file: Using sed (stream editor): sed -n '$p' fileName. Using tail: tail -1 fileName. using awk: awk 'END { print }' fileName.

How do I see the last line of a file in Linux?

To display the last part of the file, we use the tail command in the Linux system. The tail command is used to display the end of a text file or piped data in the Linux operating system. By default, it displays the last 10 lines of its input to the standard output. It is also complementary of the head command.


2 Answers

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.

like image 198
Ionuț G. Stan Avatar answered Oct 13 '22 18:10

Ionuț G. Stan


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--); } fclose($fp); 

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 = ""

like image 38
NawaMan Avatar answered Oct 13 '22 19:10

NawaMan