src/LineReader.php
private static function readBackwards($fh, int $pos): \Generator
    {
        $buffer = null;
        $bufferSize = 4096;

        if ($pos === 0) {
            return;
        }

        while (true) {
            if (isset($buffer[1])) { // faster than count($buffer) > 1
                yield array_pop($buffer);
                continue;
            }

            if ($pos === 0) {
                yield array_pop($buffer);
                break;
            }

            if ($bufferSize > $pos) {
                $bufferSize = $pos;
                $pos = 0;
            } else {
                $pos -= $bufferSize;
            }
            fseek($fh, $pos);
            $chunk = fread($fh, $bufferSize);
            if ($buffer === null) {
                // remove single trailing newline, rtrim cannot be used here
                if (substr($chunk, -1) === "\n") {
                    $chunk = substr($chunk, 0, -1);
                }
                $buffer = explode("\n", $chunk);
            } else {
                $buffer = explode("\n", $chunk . $buffer[0]);
            }
        }
    }
private static function readBackwards($fh, int $pos): \Generator
    {
        $buffer = null;
        $bufferSize = 4096;

        if ($pos === 0) {
            return;
        }

        while (true) {
            if (isset($buffer[1])) { // faster than count($buffer) > 1
                yield array_pop($buffer);
                continue;
            }

            if ($pos === 0) {
                yield array_pop($buffer);
                break;
            }

            if ($bufferSize > $pos) {
                $bufferSize = $pos;
                $pos = 0;
            } else {
                $pos -= $bufferSize;
            }
            fseek($fh, $pos);
            $chunk = fread($fh, $bufferSize);
            if ($buffer === null) {
                // remove single trailing newline, rtrim cannot be used here
                if (substr($chunk, -1) === "\n") {
                    $chunk = substr($chunk, 0, -1);
                }
                $buffer = explode("\n", $chunk);
            } else {
                $buffer = explode("\n", $chunk . $buffer[0]);
            }
        }
    }
private static function readBackwards ( $ fh , int $ pos ) : \ Generator { $ buffer = null ; $ bufferSize = 4096 ; if ( $ pos === 0 ) { return ; } while ( true ) { if ( isset ( $ buffer [ 1 ] ) ) { // faster than count($buffer) > 1 yield array_pop ( $ buffer ) ; continue ; } if ( $ pos === 0 ) { yield array_pop ( $ buffer ) ; break ; } if ( $ bufferSize > $ pos ) { $ bufferSize = $ pos ; $ pos = 0 ; } else { $ pos -= $ bufferSize ; } fseek ( $ fh , $ pos ) ; $ chunk = fread ( $ fh , $ bufferSize ) ; if ( $ buffer === null ) { // remove single trailing newline, rtrim cannot be used here if ( substr ( $ chunk , - 1 ) === "\n" ) { $ chunk = substr ( $ chunk , 0 , - 1 ) ; } $ buffer = explode ( "\n" , $ chunk ) ; } else { $ buffer = explode ( "\n" , $ chunk . $ buffer [ 0 ] ) ; } } }
Read a file from the end using a buffer.

This is way more efficient than using the naive method
of reading the file backwards byte by byte looking for
a newline character.

@see http://stackoverflow.com/a/10494801/147634
@param resource $fh
@param int $pos
@return \Generator
Read a file from the end using a buffer .