I am trying to find a quick way of reading from a csv file, by first skipping a number of lines, reading about 20 lines, then stopping the read. the only solution right now is using fread, which is pretty inefficient.
3 Answers
The only way to scroll through a CSV that respects the particular CSV format is to invoke a parser. The fastest CSV parser is the built in fgetcsv. Thus, that's going to be fastest of all possible reliable methods:
function csv_slice($fp, $offset = 0, $length = 0) {
$i = 0;
while (false !== ($row = fgetcsv($fp))) {
if ($i++ < $offset) continue;
if (0 < $length && $length <= ($i - $offset - 1)) break;
yield $row;
}
}
Used like:
$fp = fopen('file.csv', 'r');
print_r(
iterator_to_array(
csv_slice($fp, 5, 2) // start after 5th row, return 2 rows
)
);
fclose($fp);
I've used generators here to keep the memory consumption low. You can easily replace with a temporary array if you prefer.
If you can make some assumptions about line endings, then you can just read byte-by-byte until you found the range of line endings. But, frankly, I wouldn't do that.
Comments
Let's say if you have this piece of code below
<?php
$row = 1;
if (($handle = fopen("ptt.csv", "r")) !== FALSE) {
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
$num = count($data);
$row++;
for ($c=0; $c < $num; $c++) {
echo "<TR>"; // OPEN ROW
if(strpos($data[$c], 'Finished') !== false) {
$c++;
echo "<TD nowrap>" . $data[$c] . "</TD>";
}else{
echo "<TD nowrap>" . $data[$c] . "</TD>";
}
echo "</TR>"; // CLOSE ROW
}
}
fclose($handle);
}
?>
if you add
if($row == 20){ $row++; continue; }
after the while loop
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
if($row == 20){ $row++; continue; }
now, let's say if you want to start from row 20, it would continue reading
let's take another example. if you want to stop reading at line 40 starting from 1 you can insert
if($row == 40){ $row++; exit; }
1 Comment
Try using file(). It will read all the lines of your file and then you may read it the way as you want. For example:
$lines = file("myfile.txt");
$lineCounter = count($lines);
if($lineCounter > 20){
$startsAt = 21; //Skip 20 lines
for($i = $startsAt; $i < $lineCounter; $i++){
$line = $lines[$i];
//Do whatever you want with the line contents
}
}
fgetcsv()will be using internally anyways. one way or another, those lines have to get read into php so it can figure out where the line breaks are. if you choose to skip/ignore those lines, that's not php's problem - the data HAS to get read.file(), and then usearray_slice()to get the lines you want.