Search code examples
phpcsvfopenfgetcsv

Why is fgetcsv() function aggregating the consecutive EMPTY fields into ONE field, and putting it into ONE array position?


Here is the CSV file:

a.csv:

"a","b",,"c",,"d","e","f",,"g","h","i","j",,,,,,,,,,,,,,"k",,,,,,,,,,,,,,,"l","m,n","o"

Now in this CSV file, , is the delimiting character between fields. So the first field is a, the second field is b, the third field is empty, the fourth field is c, the fifth field is empty again, and so on.

Here is my example code:

index.php:

$file = fopen("a.csv", "r");

while ( !( ($line = fgetcsv($file, ',', '"')) === false ) ) {
    print_r($line);echo "<br>";
}

EXPECTED OUTPUT:

I was expecting this code snippet to print something like:

Array ( [0] => a, [1] => b [2] => [3] => c [4] => [5] => d ...so on

OUTPUT I GOT:

Actual output I got:

Array ( [0] => a, [1] => b [2] => ,, [3] => c [4] => ,, [5] => d [6] => , [7] => e [8] => , [9] => f [10] => ,, [11] => g [12] => , [13] => h [14] => , [15] => i [16] => , [17] => j [18] => ,,,,,,,,,,,,,, [19] => k [20] => ,,,,,,,,,,,,,,, [21] => l [22] => , [23] => m,n [24] => , [25] => o [26] => ) 

QUESTION:

  1. Firstly, why am I getting those random commas? I say random because, as you can see, there is a comma after the first element a, then there is no comma after the second element b, and there is no comma after c either (and so on).

  2. For the fields which do Not have a value, i.e. which are empty, why is it aggregating several several fields, e.g. in the field shown at index 18, about 14 EMPTY fields have been aggregated and put into one array position. Why? The result of this is that this output array was supposed to contain 43 elements, and now it contains 26.

How do I fix these problems and get the expected output?

Note: I am able to change the separator and field-enclosure values in the CSV File.


Solution

  • You've got the wrong parameters to fgetcsv. Note the second parameter, length, which you're missing. In fact, as you just seem to need the default behaviour, this should work:

    while ( !( ($line = fgetcsv($file)) === false ) ) {
    

    What you're actually doing in your original code is setting the CSV line length to ",", the delimiter to a double quote, and not setting the enclosure, which means that's defaulting to a double quote, too. This is clearly confusing the parser.

    (Incidentally, you may also want to make sure the file exists before using it, otherwise your code will go into an infinite loop as fgetcsv returns NULL.)