fgetcsv()使用变音符号(即非ASCII)删除字符 - 如何修复?

时间:2010-09-03 16:39:11

标签: php csv character-encoding

  

类似问题:
  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位字符编码。

问题:&{em>某些(并非所有!)字符超过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的方法吗?

1 个答案:

答案 0 :(得分:13)

事实证明,我没有充分阅读文档 - fgetcsv()只是有点二进制安全。对于纯ASCII而言是安全的< 127,但是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
}