karuhanga
karuhanga

Reputation: 3322

PHP skip lines while reading

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.

Upvotes: 2

Views: 4825

Answers (3)

unixmiah
unixmiah

Reputation: 3145

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; }

Upvotes: 1

bishop
bishop

Reputation: 39354

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.

Upvotes: 2

CarlosCarucce
CarlosCarucce

Reputation: 3569

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
    }

}

Upvotes: -1

Related Questions