PHP:即使存在,也会出现未定义的索引问题

10
这里是需要翻译的内容:

它让我很疯狂...我试图解析一个csv文件,但出现了非常奇怪的行为。

这是csv文件:

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

现在是php代码

$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();
        }
    }
}

和输出

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)

关键字"action"在$temp中存在,但$temp['action']返回Undefinedarray_key_exists返回false。我尝试使用不同的关键字名称,但仍然是相同的结果。其他关键字没有任何问题。

这是怎么回事?

PS:第110行是print_r($temp['action']);

编辑1

如果我在每行csv的开头添加另一个空字段,则action将正确显示

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

我也试了一下你的代码,没有出现错误,我可以输出$temp['action']的值。你确定你的CSV文件和发布的一样吗? - David Hirst
@David $headers是在if(!isset($headers))中设置的,是的,CSV文件完全相同。 - Spin0us
@ojovirtual: var_dump 产生了相同的错误。 - Spin0us
我刚刚在另一个PHP安装上尝试了这段代码,结果一样。action返回bool(false),id返回bool(true)。 - Spin0us
2
可能字符串“action”的开头有额外的“控制”字符。我建议使用bin2hex显示数组键,以便确切地了解“action”数组键包含哪些字符。提示是当您向输入行添加额外列时,“action”单词是正确的。您还可以“修剪”该单词,因为这将删除空白。 - Ryan Vincent
显示剩余7条评论
6个回答

12

可能第一行开头有一些特殊字符,而trim函数没有将其删除。

尝试使用以下方法删除每个非单词字符:

// Identify headers
if(!isset($headers))
{
    for($i=0;$i<$cols;$i++)
    {
        $headers[preg_replace("/[^\w\d]/","",strtolower($row[$i]))] = $i;
....

4
如果你的CSV文件采用UTF-8编码,请确保它是UTF-8而不是UTF-8-BOM格式。(你可以在Notepad++的"编码"菜单中进行检查)

2
我在使用UTF-8编码生成的MS Excel CSV文件中也遇到了同样的问题。在读取CSV文件的代码中添加以下代码可以解决这个问题:
$handle = fopen($file, 'r');

// ...

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

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

它的作用是检查UTF-8 字节序标记是否存在。如果有,则将指针移动到BOM之后。这不是通用解决方案,因为还有其他类型的BOM,但您可以根据需要进行调整。

1

很抱歉我在一个旧的线程上发帖,但我认为我的答案可以补充已经提供的答案...

我正在使用来自Windows 10主机的Vagrant guest VM(Ubuntu 16.04)进行工作。当我第一次遇到这个bug时(在我的情况下,使用Laravel和csv文件填充数据库表),@ojovirtual的答案立即有意义,因为Windows和Linux之间可能存在格式问题。

@ojovirtual的答案对我并不完全有效,所以我最终通过Bash执行touch new_csv_file.csv,并将“有问题”的CSV文件(最初是在我的Windows 10主机上创建的)粘贴到这个新创建的文件中。这确实解决了我的问题-学习和调试更多肯定是好的,但我只是想完成我的特定任务。


0

我为这个问题苦苦挣扎了几个小时,才意识到问题是由于数组中存在空键值引起的。请确保没有任何键值为空。


0

我曾经为这个问题苦恼了很久,直到我意识到我的代码块被运行了两次。

第一次运行时,索引存在,我的数组正确打印出来;第二次运行时,索引不存在,触发了通知错误。这让我想知道:“为什么我的明显存在且正确打印的数组会触发'未定义的索引'通知”。:)

也许这能帮助某些人。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接