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.
-
3why avoid fread? that's what `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. – Marc B Jul 20 '16 at 19:29
-
You could read the whole file into an array with `file()`, and then use `array_slice()` to get the lines you want. – Barmar Jul 20 '16 at 19:30
-
But if the file is big, that will be slower and wasteful. Your original way is probably the best. – Barmar Jul 20 '16 at 19:31
-
The problem is a file is not arranged in lines but in blocks, to skip a number of lines you need to scan through the file to find the newline characters, so using a reader to read lines and discard them is pretty much unavoidable. – apokryfos Jul 20 '16 at 19:40
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.

- 37,830
- 11
- 104
- 139
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; }
-
@ref: http://stackoverflow.com/questions/10901113/skip-the-first-line-of-a-csv-file – unixmiah Jul 20 '16 at 19:37
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
}
}

- 3,420
- 1
- 28
- 51