0

I have a large text file in this form:

This is a linie of text.
This is a linie of text.
This is a linie of text.
This is a linie of text.

This is a linie of text.
This is a linie of text.

This is a linie of text.
This is a linie of text.
This is a linie of text.

etc. I want to output the last couple of chunks/blocks of text from this file in my website. I currently use this:

$line = '';

$f = fopen('output.log', '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);
}

echo $line;

That shows just the last line. Any thought about this would be awesome! Thanks! Edit: All blocks are separated by empty lines, the script should print the last few blocks.

Cyrus
  • 7
  • 6
  • What's your definition of "last chunks of text"? How do you determine which part to use? And why do you work character by character? With `fgets()` you can read entire lines at once. – Till Helge May 22 '13 at 11:34
  • look here, might help you http://stackoverflow.com/questions/3234580/read-a-file-backwards-line-by-line-using-fseek – k102 May 22 '13 at 11:39
  • A chunk of text from this file is determined by n lines of text separated by an empty line, followed by another 'chunk' of text. – Cyrus May 22 '13 at 11:47

4 Answers4

1

unless the file is prohibitively large, you could just explode it

$allLines = explode("\n", file_get_contents('your/file') );
$endLines = array_slice( $allLines, -2 );
echo implode("\n", $endLines );

If you want to match blocks containing any number of lines, you could explode with a double line break "\n\n"

If the whitespace characters aren't reliably uniform, you could use preg_match. e.g.

$allBlocks = preg_split( '/[\n\r]\s*[\n\r]/', file_get_contents('your/file'), -1, PREG_SPLIT_NO_EMPTY );
Tim
  • 8,036
  • 2
  • 36
  • 52
0

Read in the file with file_get_contents() and the explode by double new line, then pick out the last element with array_pop().

silkfire
  • 24,585
  • 15
  • 82
  • 105
  • You can use file() to split the contents into an array :) – Phil Cross May 22 '13 at 11:36
  • @PhilCross `file()` reads the document line by line, he's actually interested in the last block, not indivual lines if I understood OP's request correctly. – silkfire May 22 '13 at 11:37
  • Sorry, I miscommunicated the suggestion, instead of `file_get_contents()` then `explode()`, file() will do both functions for you, you could then just grab the last couple of array elements :) – Phil Cross May 22 '13 at 11:40
  • All blocks are separated by empty lines, the script should print the last few blocks. I'll update the OP too. – Cyrus May 22 '13 at 11:45
  • @PhilCross True, but how will you then know where the blocks begin and end? – silkfire May 22 '13 at 11:46
  • I just want to print the lines of text between empty lines. – Cyrus May 22 '13 at 11:49
  • My solution is exactly the one as Tim's, that I what I wanted to state out :) – silkfire May 22 '13 at 11:50
  • Using `FILE_SKIP_EMPTY_LINES` in the file function will automatically remove empty lines from the text. You can find out the number of lines in the file by using count() on the array :), then just user $file[lineNumber] to get the line, for example, `$fileContents[count($file)]` – Phil Cross May 22 '13 at 12:02
0

Here go:

file.txt

This is a linie of text.
This is a linie of text.
This is a linie of text.
This is a linie of text.

This is a linie of text.
This is a linie of text.

This is a linie of text.
This is a linie of text.
This is a linie of text.

process.php:

$fileContents = file('file.txt', FILE_SKIP_EMPTY_LINES);
$numberOfLines = count($fileContents);

for($i = $numberOfLines-2; $i<$numberOfLines; $i++)
{
    echo $fileContents[$i];
}

This will output the last 2 lines of text from the file

Alternatively, use substr to return the last 50 letters of text:

$fileContents = file_get_contents('file.txt');
echo subtr($fileContents, -50, 50);
Phil Cross
  • 9,017
  • 12
  • 50
  • 84
  • I like this approach. But it lacks the formatting. Eg: "This is a line of textThis is a line of text" - these two should be on 2 separate lines. – Cyrus May 22 '13 at 23:44
  • You can then use: `implode("\n", array(array_slice($fileContents, -2,2));` This will join the array elements by a new line, and only retrieve the last 2 elements. If you want to retrieve the last 3 elements, just replace `-2` with `-3`, and `2` with `3` – Phil Cross May 23 '13 at 06:54
  • 1
    I choose this. Thank you all for contributing! – Cyrus May 27 '13 at 22:17
0

For large files this code will work faster than regular expressions .

$mystring = file_get_contents('your/file');    
$pos = strrpos($mystring, "\n")
if($pos === false)
    $pos = strrpos($mystring, "\r");
$result = substr($mystring, $pos);