1

尝试使用在 Internet 上找到的以下代码(包括PHP 函数定义页面filegetcsv)来解析 CSV 文件并对其进行处理:

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. 我没有使用 Mac 上的 Excel 生成的 CSV(那里有一个奇怪的错误
  4. PHP版本5.1.6,所以功能应该没有问题
  5. 我知道文件不是太大,也不是格式错误,因为我一直在缩小原始文件以查看是否有问题,最后只是在记事本中创建了一个自定义文件,其中只有两行,例如:

    值 1A、值 1B、值 1C、值 1D

仍在循环并且不提供任何数据。这是我现在正在使用的完整代码(使用一个大于行数的变量,所以我可以证明它会无限循环而实际上没有给我的服务器一个无限循环)

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等等的目的是为了防止这种事情发生。

4

2 回答 2

6

毫无疑问这里发生了什么:文件没有成功打开。这就是为什么$handle是 abool而不是资源(var_dump($handle)自己确认)。

fgetcsv然后返回null(不是false!),因为有一个错误,并且您的测试没有选择它,因为您正在使用!== false. 正如文档所述:

如果提供了无效句柄,fgetcsv() 将返回 NULL,或者在其他错误(包括文件结尾)时返回 FALSE。

我同意返回nullfalse处理不同的错误条件并不理想,而且它违反了许多其他函数建立的先例,但这就是事实(情况可能会 更糟)。就目前而言,您可以简单地将测试更改为

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)

我相信你明白这里出了什么问题。这就是为什么我永远不会在条件句中进行赋值的原因。我不在乎这是可能的。我不在乎它是否更短。我什至不在乎如果分配被取出,有时编写循环会变得不那么“优雅”。如果您重视自己的理智,请考虑这样做。

于 2011-12-07T17:26:21.683 回答
0
            $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);
            }

尝试给定代码片段一次,因为我注意到您在代码中遗漏了一些重要的东西。

于 2018-09-29T16:19:36.213 回答