Reputation: 777
I am trying to do this exact function, only want to be able to display the last 20 lines of the document?
$file = fopen("/tmp/$importedFile.csv","r");
while ($line = fgetcsv($file))
{
$i++;
$body_data['csv_preview'][] = $line;
if ($i > 20) break;
}
fclose($file);
I have tried changing the "r"
in $file = fopen("/tmp/$importedFile.csv","r");
however it seems there is only variations of where to put the pointer with read and write.
I feel this could be an easy one. my apologies.
Upvotes: 1
Views: 2179
Reputation: 147
I came up with this:
$file = fopen("/tmp/$importedFile.csv","r");
$start = count( file( $file ) ) - 20;
$i = 0;
while ($line = fgetcsv($file)) {
$i++;
if ( $i > $start ) $body_data['csv_preview'][] = $line;
}
fclose($file);
//Body_data has now the last 20 lines.
Hope this helps
Upvotes: 1
Reputation: 32953
This is one way
$fileend = array();
$file = fopen("/tmp/$importedFile.csv","r");
while ($line = fgetcsv($file))
{
// we have a line, so if $fileend already contains the required number
// of lines we have to make some room.
if (count($fileend) > 20) {
$fileend=array_shift($fileend);
}
// add freshly read line to array's end
array_push($fileend,$line);
}
fclose($file);
// at this point $fileend will contain the 20 last lines of the file.
I can't guarantee you that it will be blindingly fast though...
A muich faster way would be to store the lines in a fixed-size circular buffer, which is easier than it sounds
$i=0;
while ($line = fgetcsv($file))
{
// store as linenumber modulo 20 'th element in array
$circularbuffer[$i % 20] = $line;
$i++;
}
And then to read it
// must start reading after last written element, $i has the correct value.
// and we will read 20 times - same modulo calculation to "circulate" buffer
for ($j=$i;$j<$i+20;$j++) {
$body_data['csv_preview'][] = $circularbuffer[$j%20];
}
Obviously the big advantage here is that you read the file only once, and I think that the read operation is by far the costliest (in execution time) part of the function.
Upvotes: 0
Reputation: 59699
One way to do this is to use an SqlFileObject
. First, you need to know how many lines are in the file, which you can calculate like this:
$filename = "/tmp/$importedFile.csv";
// Create a new object for the file
$file = new SplFileObject( $filename, "r");
$lines = 0;
while ( !$file->eof()) {
$file->fgets();
$lines++;
}
Now you know there are $lines
number of lines in the file. Then, you have to seek to the $lines - 20
line number, and read your CSV data until EOF, like this:
$file->seek( $lines - 20);
while ( !$file->eof()) {
$body_data['csv_preview'][] = $file->fgetcsv();
}
Perhaps there is a more efficient way to calculate $lines
. Also, you should confirm that there is more than 20 lines in the file before attempting to seek()
to $lines - 20
.
Upvotes: 2
Reputation: 2000
Your code returns first 20 lines. Try modify it for last 20 lines
if($i > 20)
array_shift($body_data['csv_preview'])
Upvotes: 1