缺少csv中字段的第一个字符

时间:2011-04-22 14:18:46

标签: php csv fgetcsv

我正在使用php中的csv导入脚本。它工作正常,除了字段开头的外来字符。

代码看起来像这样

if (($handle = fopen($filename, "r")) !== FALSE)
{
     while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) 
         $teljing[] = $data;

     fclose($handle);
}

以下是显示我的问题的数据示例

føroyskir stavir, "Kr. 201,50"
óvirkin ting, "Kr. 100,00"

这将导致以下

array 
(
     [0] => array 
          (
                 [0] => 'føroyskir stavir',
                 [1] => 'Kr. 201,50'
          )
     [1] => array 
          (
                 [0] => 'virkin ting', <--- Should be 'óvirkin ting'
                 [1] => 'Kr. 100,00'
          )
)

我已经在php.net的一些评论中看到了这种行为,我尝试ini_set('auto_detect_line_endings',TRUE);来检测行结尾。没有成功。

有谁熟悉这个问题?

编辑:

谢谢你,这个问题现在已经解决了。

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

是解决方案。

2 个答案:

答案 0 :(得分:6)

来自fgetcsv()的{​​{3}}:

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

答案 1 :(得分:0)

从PHP.net/fgetcsv评论中复制:

  

keke at marketruler dot com   04-Feb-2010 11:18请注意fgetcsv,   至少在PHP 5.3或之前,将   不适用于UTF-16编码文件。   你的选择是转换整个   归档到ISO-8859-1(或latin1),或   逐行转换并转换每一个   然后进入ISO-8859-1编码行   使用str_getcsv(或兼容   向后兼容的实现)。   如果你需要阅读非拉丁语   字母表,可能最好转换为   UTF-8。

     

请参阅str_getcsv了解   向后兼容的版本   用PHP&lt; 5.3,并查看utf8_decode   对于Rasmus写的函数   Andersson提供utf16_decode。   我添加的修改是   BOP出现在文件的顶部,   然后不在后续行。那么你   需要存储endian-ness,和   然后在每次后续重新发送   线解码。这个修改版本   返回字节序,如果不是   可用的:

<?php
/**
 * Decode UTF-16 encoded strings.
 *
 * Can handle both BOM'ed data and un-BOM'ed data.
 * Assumes Big-Endian byte order if no BOM is available.
 * From: http://php.net/manual/en/function.utf8-decode.php
 *
 * @param   string  $str  UTF-16 encoded data to decode.
 * @return  string  UTF-8 / ISO encoded data.
 * @access  public
 * @version 0.1 / 2005-01-19
 * @author  Rasmus Andersson {@link http://rasmusandersson.se/}
 * @package Groupies
 */
function utf16_decode($str, &$be=null) {
    if (strlen($str) < 2) {
        return $str;
    }
    $c0 = ord($str{0});
    $c1 = ord($str{1});
    $start = 0;
    if ($c0 == 0xFE && $c1 == 0xFF) {
        $be = true;
        $start = 2;
    } else if ($c0 == 0xFF && $c1 == 0xFE) {
        $start = 2;
        $be = false;
    }
    if ($be === null) {
        $be = true;
    }
    $len = strlen($str);
    $newstr = '';
    for ($i = $start; $i < $len; $i += 2) {
        if ($be) {
            $val = ord($str{$i})   << 4;
            $val += ord($str{$i+1});
        } else {
            $val = ord($str{$i+1}) << 4;
            $val += ord($str{$i});
        }
        $newstr .= ($val == 0x228) ? "\n" : chr($val);
    }
    return $newstr;
}
?>

Trying the "setlocale" trick did not work for me, e.g.

<?php
setlocale(LC_CTYPE, "en.UTF16");
$line = fgetcsv($file, ...)
?>
  

但这可能是因为我的平台   不支持它。但是,fgetcsv   仅支持单个字符   分隔符等,并抱怨如果   你传入了UTF-16版本的说法   性格,所以我放弃了   快。

     

希望这对某人有帮助   那里。