0

After opening CSV files with fopen(), I'm currently skipping the three first lines of these files like this:

fgetcsv($file, 0, ';');
fgetcsv($file, 0, ';');
fgetcsv($file, 0, ';');

Is there a nicer method to skip the n first lines ?

DevonDahon
  • 7,460
  • 6
  • 69
  • 114
  • 1
    There is a useful addage you may wish to apply "If it aint broke, dont fix it". There is nothing wrong with what you are doing – RiggsFolly Jul 22 '20 at 15:43
  • 1
    The benefit of doing what you are doing, it it is completely self documetary, and the next person that comes along to maintain the code will have ZERO problems working out whats going on – RiggsFolly Jul 22 '20 at 15:53
  • 1
    @RiggsFolly You're right and I'll stay with it, I thought there was maybe an option I didn't see about it. – DevonDahon Jul 22 '20 at 15:55
  • With the headline being, *"skip the N first lines"*, having a better-scaling solution would be in order. I'd like to see the face of the next person reading the code if OP needed to skip the first 100 lines in a future implementation. ^_^ – Markus AO Jul 22 '20 at 19:21
  • Does this answer your question? [Skip first line of fgetcsv method](https://stackoverflow.com/questions/14372730/skip-first-line-of-fgetcsv-method) – Dharman Jul 25 '20 at 11:21
  • @Dharman The answers from RiggsFolly and MarkusAO are better solutions for me. – DevonDahon Jul 26 '20 at 08:18

3 Answers3

1

If you need to skip more than a handful of lines, simply add one instance of the "throw-away read" code you already have inside a for loop. Number of loops equals lines skipped (e.g. 8 lines):

for ($i = 0; $i < 8; $i++) { 
    fgetcsv($file, 0, ';');
}

Do this before you begin your main while loop getting the CSV lines you care about. You could turn the loop into a utility function -- if you find yourself doing this often at different skip lengths.

function fskipcsv_lines($handle, int $lines) {
    for ($i = 0; $i < $lines; $i++) { 
        fgetcsv($handle, 0, ';');
    }
}

Simple enough. Same construct applies for the "dumb" repetition of any other function you don't need to get a a return value from, that simply needs to be called N times.

P.S. Don't place the "skip line" check routine inside your main CSV iteration loop. Why? Because the check (e.g. $row < 3; or in_array($row, $skips)) would happen at each loop iteration. Suppose you need to read 100,000+ lines, the overhead will start adding up, unnecessarily burdening each loop iteration for the first (now past) few lines' sake.

Markus AO
  • 4,771
  • 2
  • 18
  • 29
  • In the function, the `$handle` argument doesn't require `&` a reference (which I initially had). A stream resource handle retains its state across contexts/scopes, unlike a regular value-holding variable that's only affected in a function's scope unless passed by reference. (If someone can reference that from the manual, or point out exceptions, please do.) – Markus AO Jul 22 '20 at 17:07
  • P.S. I ran a test to compare the "in-loop" approaches with a 50K rows / 8MB CSV file (took 108MB memory when added into an array). A simple in-loop row number comparison filtering made virtually no difference to the execution time. The `in_array` filtering was also largely transparent, with more skip-lines around a 5% runtime increase. **In any case**, it's good practice to not have redundant code iterated. There will be cases where it's consequential, and it's better to build a habit of avoiding unnecessary repetition. – Markus AO Jul 22 '20 at 18:34
  • In other notes. I tested `$csv = array_map('str_getcsv', file($file));` vs. `while($row = fgetcsv($handle)) { $csv[] = $row; }`. Runtime identical, memory/max-memory 108/122MB vs. 108/108MB. (If you don't pool it up into an array for later use, only one row's worth memory used.) Point being, if the CSV's in an array, it's trivial to unset (custom) lines. Either with `unset($csv[1], $csv[8], ...)`, or with `$skip = [1, 8,...];` and `$csv = array_diff_key($csv, array_fill_keys($skip, null));`. Don't use if you don't need the full data in an array, will munch memory. – Markus AO Jul 22 '20 at 19:01
0

Your are doing right, but this code may help if you are going to skip many. :

$skippTheseLines = array(1,2,3);
$i = 0;
$totlLines= 10000;

while (($emapData = fgetcsv($file, $totalLines, ";")) !== FALSE) {

   if(in_array($i, $skippTheseLines)) { 
       continue; 
   }else{
       // rest of your code
   }

    $i = $i + 1;
}
Asiri Hewage
  • 577
  • 3
  • 16
0

Check out this code. Similar questions: skip first line of fgetcsv method in php

$file = fopen('example.csv', 'r');  // Here example is a CSV name
$row = 1;
$number_to_skip = 3
while (($line = fgetcsv($file,0, ",")) !== FALSE) {
// $line is an array of the csv elements
if($row < $number_to_skip)
{ 
  $row++; continue;   // continue is used for skip row 0,1,2
} 
print_r($line);

}