Reading line from file

Reading files in PHP can be a tricky business if not handled correctly. Most often when confronted with reading a line from, the nearest tool to hand is the file() function. The problem with using the file() function is that it reads the whole file into an array, and thus, into memory. Any subsequent operations on the array, such as foreach() result in an internal copy of the array for PHP to work on. Should the file be a two gig log file, then the result could be up to four gigs worth of memory being devoured to gain a few hundred k of text.

A better, and more efficient way is to loop through the file stream using the stream_get_line() function. Care still needs to be taken to clear the buffer on each iteration, or the same problem could potentially arise as with the file() method.

By using this method of looping through the file, and breaking when the appropriate line is found, memory usage is minimized to only a single line of the file. Should one hundred users access this at the same time, no issues will arise as when each user could be using up to four gig each.

<?php

function readLine($file, $line_num, $delimiter=”\n”)
{
/*** set the counter to one ***/
$i = 1;

/*** open the file for reading ***/
$fp = fopen( $file, ‘r’ );

/*** loop over the file pointer ***/
while ( !feof ( $fp) )
{
/*** read the line into a buffer ***/
$buffer = stream_get_line( $fp, 1024, $delimiter );
/*** if we are at the right line number ***/
if( $i == $line_num )
{
/*** return the line that is currently in the buffer ***/
return $buffer;
}
/*** increment the line counter ***/
$i++;
/*** clear the buffer ***/
$buffer = ”;
}
return false;
}
?>

Example

<?php

/*** make sure the file exists ***/
$file = ‘my_file.txt’;

if( file_exists( $file ) && is_readable( $file ) )
{
echo readLine($file, 6);
}
else
{
echo “Cannot read from $file”;
}
?>

This method of iterating over the file and seeking to the line number works well and is memory efficient, but it would be nice to have PHP do the work for us. PHP provides the SPL File Object which will do exactly what is required.

<?php

/*** the file to read ***/
$file = ‘foo.txt’;

function readLine( $file, $line_number )
{
/*** read the file into the iterator ***/
$file_obj = new SplFileObject( $file );

/*** seek to the line number ***/
$file_obj->seek( $line_number );

/*** return the current line ***/
return $file_obj->current();
}

echo readLine( $file, 345678 );

?>

You can leave a response, or trackback from your own site.

Leave a Reply