问题 fgetcsv()在行首时忽略特殊字符!


我有一个简单的脚本,它接受一个CSV文件并将每一行读入一个数组。然后我循环浏览第一行的每一列(在我的情况下,它包含调查问题)并打印出来。调查是法语的,每当问题的第一个字符是特殊字符(é,ê,ç等)时,fgetcsv就会省略它。

值的中间的特殊字符仅在它们是第一个字符时才受影响。

我试着调试这个,但我很困惑。我做了一个var_dump与文件的内容,字符肯定在那里:

var_dump(utf8_encode(file_get_contents($_FILES['csv_file']['tmp_name'])));

这是我的代码:

if(file_exists($_FILES['csv_file']['tmp_name']) && $csv = fopen($_FILES['csv_file']['tmp_name'], "r"))
    {
        $csv_arr = array();

        //Populate an array with all the cells of the CSV file
        while(!feof($csv))
        {
            $csv_arr[] = fgetcsv($csv);
        }

        //Close the file, no longer needed
        fclose($csv);

        // This should cycle through the cells of the first row (questions)
        foreach($csv_arr[0] as $question)
        {
            echo utf8_encode($question) . "<br />";
        }

    }

6236
2018-02-10 17:32


起源

如果你使用纯ASCII,fgetcsv()只是二进制安全的 - 换句话说,根本不是。看到 stackoverflow.com/questions/3637770/...  - 基本上,使用fgets()读取数据,然后使用自定义函数解析CSV。显然这也有效: stackoverflow.com/questions/1472886/... - Piskvor


答案:


你有没有检查过 fgetcsv上的手册页?没有什么可以随意谈论这个特定的问题,但是如果没有任何问题,可能需要一些贡献。

就是这样,例如:

注意:此功能会考虑区域设置。如果LANG是例如en_US.UTF-8,此函​​数读取单字节编码的文件错误。

另外,看到它总是在行的开头,这可能是一个隐藏的换行问题吗?有这个:

注意:如果在读取Macintosh计算机上或由Macintosh计算机创建的文件时PHP无法正确识别行结尾,则启用auto_detect_line_endings运行时配置选项可能有助于解决问题。

您可能还想尝试使用不同的行结尾保存文件。


1
2018-02-10 17:36



我已经阅读了有关如何使用该功能的手册页,并且快速搜索注释区域没有弹出任何特殊字符或utf-8编码。我注意到它可能会遇到UTF-8编码问题,但如果我不对值进行编码,则值仍然不会显示。我不确定是否会有另一种解决方法。我试过用“|”作为行结束分隔符,我得到同样的问题。这很令人困惑:) - Gazillion


您是否在呼叫前正确设置了区域设置 fgetcsv()

setlocale(LC_ALL, 'fr_FR.UTF-8');

除此以外, fgetcsv() 不是多字节安全的。

确保将其设置为可用语言环境列表中显示的内容。在linux上(肯定是在debian上)你可以看到这一点

locale -a

你应该得到像......

C
en_US.utf8
POSIX

对于UTF8支持,最后选择使用utf8的编码。如果您的输入是用其他东西编码的,则需要使用适当的语言环境 - 但请确保您的操作系统首先支持它。

如果将区域设置设置为系统上不可用的区域设置,则无法帮助您。


8
2018-02-10 17:36



对不起,如果我是无知的,但什么是安全的?我添加了这行,但对我脚本的行为没有影响。手册说这个函数是二进制安全的,因为PHP 4.3.5(我们安装了php 5) - Gazillion
Multi Byte Safe =能够处理单个字符可以包含多个字节(例如UTF-8)的编码。 - Pekka 웃
啊,谢谢!我想我会留在那里:) - Gazillion
只要输入为UTF-8,这就解决了我的问题,但问题仍然存在于其他8位编码中。 - eswald
很棒的答案 - 在整个项目中将区域设置设置为UTF-8编码是否有任何缺点,而不仅仅是for fgetcsv()? - Horen


这个行为有一个 错误报告 申请,但显然它 不是一个bug


2
2017-08-16 03:43



它不是一个bug,它是一个功能。这一定是个玩笑。 - molli


我们看到了相同的结果 LANG 设置 C并通过确保将这些值包装在引号中来解决它。例如,该行

a,"a",é,"é",óú,"óú",ó&ú,"ó&ú"

传递时生成以下数组 fgetcsv()

array (
  0 => 'a',
  1 => 'a',
  2 => '',
  3 => 'é',
  4 => '',
  5 => 'óú',
  6 => '&ú',
  7 => 'ó&ú',
)

当然,你必须通过加倍来逃避值中的任何引号,但这比修复丢失的字符要麻烦得多。

奇怪的是,输入文件的UTF-8和cp1252编码都会发生这种情况。


1
2018-01-26 19:37