filegetcsv вызывает бесконечный цикл - PullRequest
0 голосов
/ 07 декабря 2011

Попытка использовать filegetcsv для анализа CSV-файла и выполнения каких-либо действий с ним, используя следующий код, который можно найти по всему Интернету, включая страницу определения функции *1003* PHP:

if (($handle = fopen("test.csv", "r")) !== FALSE) {
    while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
        print_r($data);
    }
    fclose($handle);
}

Но код дает мне бесконечный цикл предупреждений в строке $data =:

PHP Warning: fgetcsv() expects parameter 1 to be resource, boolean given in...
  1. Я знаю, что файл, который я открываю, является допустимым файлом, потому что, если я добавляю фиктивный символ к имени файла, я получаю другую ошибку и без цикла.
  2. Файл находится в папке с полными разрешениями.
  3. Я не использую CSV, сгенерированный Excel на Mac ( там есть странная ошибка )
  4. PHP версии 5.1.6, поэтому не должно быть проблем с функцией
  5. Я знаю, что файл не слишком большой или искаженный, потому что я продолжал сжимать исходный файл, чтобы увидеть, если это было проблемой, и, наконец, просто создал пользовательский файл в Блокноте с не более чем двумя строками, такими как:

    Value1A, Value1B, Value1C, Value1D

Все еще зацикливается и не дает никаких данных. Вот полный код, с которым я сейчас работаю (используя переменную, которая больше числа строк, поэтому я могу доказать, что она будет бесконечно зацикливаться, фактически не давая моему серверу бесконечный цикл)

if ($handle = fopen($_SERVER['DOCUMENT_ROOT'].'/tmp/test-csv-file.csv', 'r') !== FALSE) {
    while ((($data = fgetcsv($handle, 1000, ',')) !== FALSE) && ($row < 10)) {
        print_r($data);
        $row++;
    }
    fclose($handle);
}

Так что у меня действительно два вопроса.

1) Что я мог упускать из виду, что вызывает этот цикл? Я наполовину убежден, что это что-то действительно "простое лицо" просто ...

2) Почему рекомендуемый код для этой функции может вызвать бесконечный цикл, если файл существует, но есть какая-то неизвестная проблема? Я бы подумал, что цель !== FALSE и так далее состоит в том, чтобы предотвратить подобные вещи.

Ответы [ 2 ]

6 голосов
/ 07 декабря 2011

Нет сомнений, что здесь происходит: файл не открывается успешно.Вот почему $handle является bool вместо ресурса (var_dump($handle), чтобы подтвердить это самостоятельно).

fgetcsv затем возвращает null (не false!), Потому что есть ошибка,и ваш тест не подхватывает это, потому что вы тестируете с !== false.Как указано в документации:

fgetcsv () возвращает NULL, если указан неверный дескриптор, или FALSE для других ошибок, включая конец файла.

Я согласен с возвращением null и false для различных состояний ошибки не идеальны, и, кроме того, это противоречит прецеденту, установленному множеством других функций, но это просто так (а вещи могут быть хуже ).При существующем положении вещей вы можете просто изменить тест на

while ($data = fgetcsv($handle, 1000, ","))

, и он будет работать правильно в обоих случаях.

Обновление:

Выявляются жертвами назначения внутри условия if:

if ($handle = fopen($_SERVER['DOCUMENT_ROOT'].'/tmp/test-csv-file.csv', 'r') !== FALSE)

должно было быть

// wrap the assignment to $handle inside parens!
if (($handle = fopen($_SERVER['DOCUMENT_ROOT'].'/tmp/test-csv-file.csv', 'r')) !== FALSE)

Я уверен, что вы понимаете, что здесь пошло не так.Это причина, по которой я выбираю никогда, никогда не делать назначения внутри условных выражений .Мне все равно, что это возможно.Мне все равно, что это короче.Меня даже не волнует, что иногда написать «цикл», если задание снято, не так «элегантно».Если вы цените свое здравомыслие, подумайте о том же.

1 голос
/ 29 сентября 2018
            $row = 1;
            if (($handle = fopen($_FILES['csv-file']['tmp_name'], "r")) !== FALSE) {
                $data = fgetcsv($handle , 1000 , ",");
                while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {


                    $num = count($data);
                    echo "<p> $num fields in line $row: <br /></p>\n";
                    $row++;
                    for ($c=0; $c < $num; $c++) {
                        echo $data[$c] . "<br />\n";
                    }
                }
                fclose($handle);
            }

Попробуйте один раз дать фрагмент кода, потому что, как я заметил, в вашем коде отсутствуют некоторые важные вещи.

...