Read file lines backwards (fgets) with php

If the file is not so big you can use file():

$lines = file($file);
for($i = count($lines) -1; $i >= 0; $i--){
    echo $lines[$i] . '<br/>';
}

However, this requires the whole file to be in memory, that's why it is not suited for really large files.


Here is my solution for just printing the file backwards. It is quite memory-friendly. And seems more readable (IMO [=in my opinion]).

It goes through the file backwards, count the characters till start of a line or start of the file and then reads and prints that amount of characters as a line, then moves cursor back and reads another line like that...

  if( $v = @fopen("PATH_TO_YOUR_FILE", 'r') ){ //open the file
    fseek($v, 0, SEEK_END); //move cursor to the end of the file
    /* help functions: */
    //moves cursor one step back if can - returns true, if can't - returns false
    function moveOneStepBack( &$f ){ 
      if( ftell($f) > 0 ){ fseek($f, -1, SEEK_CUR); return true; }
        else return false;
    }
    //reads $length chars but moves cursor back where it was before reading 
    function readNotSeek( &$f, $length ){ 
      $r = fread($f, $length);
      fseek($f, -$length, SEEK_CUR);
      return $r;  
    }

    /* THE READING+PRINTING ITSELF: */
    while( ftell($v) > 0 ){ //while there is at least 1 character to read
      $newLine = false;
      $charCounter = 0;

      //line counting
      while( !$newLine && moveOneStepBack( $v ) ){ //not start of a line / the file
        if( readNotSeek($v, 1) == "\n" ) $newLine = true;
        $charCounter++;              
      } 

      //line reading / printing
      if( $charCounter>1 ){ //if there was anything on the line
        if( !$newLine ) echo "\n"; //prints missing "\n" before last *printed* line            
        echo readNotSeek( $v, $charCounter ); //prints current line  
      }   

    }
    fclose( $v ); //close the file, because we are well-behaved
  }

Of course replace PATH_TO_YOUR_FILE with your own path to your file, @ is used when opening the file, because when the file is not found or can't be opened - warning is raised - if you want to display this warning - just remove the error surpressor '@'.


First way:

$file = file("test.txt");
$file = array_reverse($file);
foreach($file as $f){
    echo $f."<br />";
}

Second Way (a):

To completely reverse a file:

$fl = fopen("\some_file.txt", "r");
for($x_pos = 0, $output = ''; fseek($fl, $x_pos, SEEK_END) !== -1; $x_pos--) {
    $output .= fgetc($fl);
    }
fclose($fl);
print_r($output);

Second Way (b): Of course, you wanted line-by-line reversal...


$fl = fopen("\some_file.txt", "r");
for($x_pos = 0, $ln = 0, $output = array(); fseek($fl, $x_pos, SEEK_END) !== -1; $x_pos--) {
    $char = fgetc($fl);
    if ($char === "\n") {
        // analyse completed line $output[$ln] if need be
        $ln++;
        continue;
        }
    $output[$ln] = $char . ((array_key_exists($ln, $output)) ? $output[$ln] : '');
    }
fclose($fl);
print_r($output);


Try something simpler like this..

print_r(array_reverse(file('myfile.txt')));

Tags:

Php

File

Fgets