【问题标题】:fgetcsv() ignores special characters when they are at the beginning of line!fgetcsv() 在行首忽略特殊字符!
【发布时间】:2011-01-15 09:19:20
【问题描述】:

我有一个简单的脚本,它接受一个 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 />";
        }

    }

【问题讨论】:

标签: php csv fgetcsv


【解决方案1】:

在致电fgetcsv() 之前,您是否正确设置了您的区域设置?

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

否则,fgetcsv() 不是多字节安全的。

确保将其设置为出现在可用语言环境列表中的内容。在 linux 上(当然在 debian 上)你可以通过这样做来看到这一点

locale -a

你应该得到类似...

C
en_US.utf8
POSIX

对于 UTF8 支持,请选择末尾带有 utf8 的编码。如果您的输入使用其他内容进行编码,则您需要使用适当的语言环境 - 但请确保您的操作系统首先支持它。

如果您将语言环境设置为系统上不可用的语言环境,它将无济于事。

【讨论】:

  • 对不起,如果我表现得无知,但什么是 mb-safe?我添加了对我的脚本行为没有影响的行。手册说该函数自 PHP 4.3.5 起是二进制安全的(我们安装了 php 5)
  • 多字节安全 = 能够处理单个字符可以包含多个字节的编码(例如 UTF-8)。
  • 只要输入是 UTF-8 就可以解决我的问题,但其他 8 位编码的问题仍然存在。
  • 很好的答案 - 在整个项目中将语言环境设置为 UTF-8 编码有什么缺点,而不仅仅是fgetcsv()
【解决方案2】:

这种行为有一个bug report 申请,但显然是isn't a bug

【讨论】:

  • 这不是错误,而是一项功能。这一定是个笑话。
【解决方案3】:

您是否已经查看了manual page on fgetcsv?没有什么直接谈论这个特定问题,但如果这里没有任何内容,一些贡献可能值得一看。

有这个,例如:

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

另外,看到它总是在行首,难道这真的是一个隐藏的换行问题?有这个:

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

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

【讨论】:

  • 我已经阅读了有关如何使用该功能的手册页,并且在评论区快速搜索并没有弹出任何特殊字符或 utf-8 编码的内容。我注意到 UTF-8 编码可能会出现问题,但如果我不对这些值进行编码,该值仍然不会显示。我不确定是否有其他方法可以解决这个问题。我尝试使用“|”作为行尾分隔符,我遇到了同样的问题。这很令人困惑:)
【解决方案4】:

我们看到将LANG 设置为C 的结果相同,并通过确保将这些值括在引号中来解决此问题。例如,行

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

通过fgetcsv()时生成如下数组:

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

当然,您必须通过将值加倍来转义值中的任何引号,但这比修复丢失的字符要容易得多。

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

【讨论】:

    猜你喜欢
    • 2013-12-11
    • 2023-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-18
    • 2018-04-18
    • 1970-01-01
    相关资源
    最近更新 更多