12

It drives me crazy ... I try to parse a csv file and there is a very strange behavior.

Here is the csv

action;id;nom;sites;heures;jours
i;;"un nom a la con";1200|128;;1|1|1|1|1|1|1

Now the php code

$required_fields = array('id','nom','sites','heures','jours');
if (($handle = fopen($filename, "r")) !== FALSE)
{
    $cols = 0;
    while (($row = fgetcsv($handle, 1000, ";")) !== FALSE)
    {
        $row = array_map('trim',$row);
        // Identify headers
        if(!isset($headers))
        {
            $cols = count($row);
            for($i=0;$i<$cols;$i++) $headers[strtolower($row[$i])] = $i;
            foreach($required_fields as $val) if(!isset($headers[$val])) break 2;
            $headers = array_flip($headers);
            print_r($headers);
        }
        elseif(count($row) >= 4)
        {
            $temp = array();
            for($i=0;$i<$cols;$i++)
            {
                if(isset($headers[$i]))
                {
                    $temp[$headers[$i]] = $row[$i];
                }
            }
            print_r($temp);
            print_r($temp['action']);
            var_dump(array_key_exists('action',$temp));
            die();
        }
    }
}

And the output

Array
(
    [0] => action
    [1] => id
    [2] => nom
    [3] => sites
    [4] => heures
    [5] => jours
)
Array
(
    [action] => i
    [id] => 
    [nom] => un nom a la con
    [sites] => 1200|128
    [heures] => 
    [jours] => 1|1|1|1|1|1|1
)
<b>Notice</b>:  Undefined index: action in <b>index.php</b> on line <b>110</b>
bool(false)

The key "action" exists in $temp but $temp['action'] returns Undefined and array_key_exists returns false. I've tried with a different key name, but still the same. And absolutely no problem with the others keys.

What's wrong with this ?

PS: line 110 is the print_r($temp['action']);

EDIT 1

If i add another empty field in the csv at the begining of each line, action display correctly

;action;id;nom;sites;heures;jours
;i;;"un nom a la con";1200|128;;1|1|1|1|1|1|1
12
  • Where is $headers being set? Commented Mar 20, 2014 at 10:27
  • Why do you print_r($temp['action']) when $temp['action'] isn't an array? Commented Mar 20, 2014 at 10:27
  • That probably won't help you much, but I just tested it myself and there were no problems at all; key existed. Commented Mar 20, 2014 at 10:28
  • I just tried your code as well, I also do not get an error and I can echo out the value of $temp['action']; Are you sure your CSV is the same as posted? Commented Mar 20, 2014 at 10:35
  • 2
    It is possible that there are extra 'control' characters at the start of the string 'action'. i suggest showing the array keys using bin2hex to see exactly what character make up the 'action' array key. the clue is when you add an extra column to the input line then the word 'action' is ok. You could also 'trim' the word as that would remove whitespace as well. Commented Mar 20, 2014 at 11:12

6 Answers 6

12

Probably there is some special character at the beginning of the first line and trim isn't removing it.

Try to remove every non-word character this way:

// Identify headers
if(!isset($headers))
{
    for($i=0;$i<$cols;$i++)
    {
        $headers[preg_replace("/[^\w\d]/","",strtolower($row[$i]))] = $i;
....
Sign up to request clarification or add additional context in comments.

Comments

5

If your CSV file is in UTF-8 encoding,

make sure that it's UTF-8 and not UTF-8-BOM.

(you can check that in Notepad++, Encoding menu)

Comments

2

I had the same problem with CSV files generated in MS Excel using UTF-8 encoding. Adding the following code to where you read the CSV solves the issue:

$handle = fopen($file, 'r');

// ...

$bom = pack('CCC', 0xef, 0xbb, 0xbf);

if (0 !== strcmp(fread($handle, 3), $bom)) {
    fseek($handle, 0);
}
// ...

What it does, is checking for the presence of UTF-8 byte order mark. If there is one, we move the pointer past BOM. This is not a generic solution since there are other types BOMs, but you can adjust it as needed.

Comments

1

Sorry I am posting on an old thread, but thought my answer could add to ones already provided here...

I'm working with a Vagrant guest VM (Ubuntu 16.04) from a Windows 10 host. When I first came across this bug (in my case, seeding a database table using Laravel and a csv file), @ojovirtual's answer immediately made sense, since there can be formatting issues between Windows and Linux.

@ojovirtual's answer didn't quite work for me, so I ended up doing touch new_csv_file.csv through Bash, and pasting contents from the 'problematic' CSV file (which was originally created on my Windows 10 host) into this newly-created one. This definitely fixed my issues - it would have been good to learn and debug some more, but I just wanted to get my particular task completed.

Comments

0

I struggled with this issue for a few hours only to realize that the issue was being caused by a null key in the array. Please ensure that none of the keys has a null value.

Comments

0

I struggled with this issue until I realised that my chunk of code has been run twice.

First run when index was present and my array was printed out properly, and the second run when index was not present and the notice error is triggered. That left me wondering "why my obviously existing and properly printed out array is triggering an 'Undefined index' notice". :)

Maybe this will help somebody.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.