【问题标题】:fgetcsv() drops characters with diacritics (i.e. non-ASCII) - how to fix?fgetcsv() 丢弃带有变音符号的字符(即非 ASCII) - 如何修复?
【发布时间】:2010-09-03 16:39:11
【问题描述】:

类似问题:
Some characters in CSV file are not read during PHP fgetcsv(),
fgetcsv() ignores special characters when they are at the beginning of line

我的应用程序有一个表单,用户可以在其中上传 CSV 文件(它的 5 个内部用户始终上传一个有效文件 - 逗号分隔、引用、记录以 LF 结尾),然后使用PHP:

$fhandle = fopen($uploaded_file,'r');
while($row = fgetcsv($fhandle, 0, ',', '"', '\\')) {
    print_r($row);
    // further code not relevant as the data is already corrupt at this point
}

由于我无法更改的原因,用户正在上传以 Windows-1250 字符集编码的文件 - 一种单字节 8 位字符编码。

问题:一些(不是全部!)超过 127 个字符(“扩展 ASCII”)被丢弃在 fgetcsv() 中。示例数据:

"15","Ústav"
"420","Špičák"
"7","Tmaň"

变成

Array (
  0 => 15
  1 => "stav"
)
Array (
  0 => 420
  1 => "pičák"
)
Array (
  0 => 7
  1 => "Tma"
)

(注意č 被保留,但Ú 被删除)

fgetcsv 的文档说“因为 4.3.5 fgetcsv() 现在是二进制安全的”,但看起来不是。我做错了什么,还是这个函数坏了,我应该寻找一种不同的方法来解析 CSV?

【问题讨论】:

  • 我马上回答,这个bug之前咬过我,已经找到原因了;想和 SO 分享这个,因为这个 bug 微妙
  • (澄清一下,Win-1250 只是输入编码。数据随后以 UTF-8 格式转换并存储在数据库中;该部分工作正常。最初读取的数据是问题所在。)

标签: php csv character-encoding


【解决方案1】:

事实证明,我没有很好地阅读文档 - fgetcsv() 只是 在某种程度上 二进制安全。纯 ASCII the documentation also says:

注意:

考虑了区域设置 通过这个功能。如果 LANG 是例如 en_US.UTF-8,一个字节的文件 编码被这个读错了 功能

换句话说,fgetcsv() 试图是二进制安全的,但实际上不是(因为它同时也弄乱了字符集),它可能会破坏它的数据读取(因为此设置未在 php.ini 中配置,而是从$LANG 读取)。

我通过阅读带有fgets 的行(它适用于字节,而不是字符)并使用a CSV function from the comment in the docs 将它们解析为一个数组来回避这个问题:

$fhandle = fopen($uploaded_file,'r');
while($raw_row = fgets($fhandle)) { // fgets is actually binary safe
    $row = csvstring_to_array($raw_row, ',', '"', "\n");
    // $row is now read correctly
}

【讨论】:

  • 错误:fgets 长度必须大于 0 且 csvstring_to_array 不存在
  • 不是错误:如果没有定义它当然不存在 - 它需要明确定义,它不是内置的。 “使用评论中的 CSV 函数”和指向它的链接不清楚?
猜你喜欢
  • 1970-01-01
  • 2012-08-02
  • 2012-06-18
  • 1970-01-01
  • 2011-10-14
  • 2019-12-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多