php fgetcsv方法bug一例

在导入导出数据的时候常用的方法是:
让初始导入数据组织成csv格式.去除掉"," .然后读取合并导入
``

$fp = fopen(file);
while($data = fgetcsv($fp)){
    $res[] =   $data;
}
return $data;

fgetcsv方法在手册上面的解释是:

说明

array fgetcsv ( resource $handle [, int $length = 0 [, string $delimiter = ',' [, string $enclosure = '"' [, string $escape = '\' ]]]] )

和 fgets() 类似,只除了 fgetcsv() 解析读入的行并找出 CSV 格式的字段然后返回一个包含这些字段的数组。

在导入导出的过程中遇到了如下的问题:

CSV使用的编码格式是UTF8,并且里面存在中文.
解析出来的数组中,中文字符串出现表示不完全的问题.

原始数据是:

荔湾区西华路太保直街1号

但是通过函数处理后得到的结果是:

1号

非常奇葩的返回,如果是中文字符串乱码倒也还好解释,你为什么把我好端端的中文搞丢了

并且在测试环境和线上环境出现了表现不一致的问题. 测试环境是好用的OK的.但是线上的正式环境就会出现这样奇葩的问题.

经过仔细排查发现我线上使用的PHP是   5.2.8   而测试环境使用的PHP版本是  5.4.17

最后找到是这个函数在作怪.但是具体哪里出现的不一致问题.还没办法确定.

在手册上找到如下说明:

Note:
该函数对区域设置是敏感的。比如说 LANG 设为 en_US.UTF-8 的话,单字节编码的文件就会出现读取错误。

这里前半句是重点.也就是说你的lang设置会影响到这个函数的行为.因为不想去down源码,以黑盒的角度来研究这个问题.

查看两台机器的lang配置

echo $LANG

线上显示  en_us

而测试环境显示  en_us.UTF-8

那么en_usen_us.utf-8的区别应该是导致这个问题的罪魁祸首  .

网上找到这个问答:觉得说的有一定道理

https://serverfault.com/questions/605776/linux-locale-en-us-utf-8-vs-en-us

en_us 使用的字符集是  : ISO8859-1  而 en_us.utf-8使用的字符集是UTF-8


黑盒猜想

网上查了查资料  其实  ISO的这个编码根本支持不了中文汉字.但是从计算机的角度出发,不管你传过来是啥,我都按照我的规则去编码就是了.于是编完了返回给PHP ,PHP 不认识,就挑认识的处理.

数字是能够正常编码的 , 前面的汉字就没办法了.于是从数字开始,编码回复正常.后面只剩下一个字,而且这个字是双字节的,从函数返回上来讲应该是当做两个字来传的,但是PHP一处理一 拼接就变成了一个字(字符的编码在两个编码表中都要存在.)


既然如此,那么解决办法也就有了 .我需要尝试吧线上的机器lang设置成utf-8  或者摒弃这个函数,用个别的函数来实现这个功能.

线上机器不敢动,不确定是不是会有别影响.于是改动了代码.最终实现   fgets($line);并且使用explode来实现了解析的功能.

另外在手册中没有体现5.4和5.2之间是否有差异.也就是说这个和PHP的版本关系并不大.应该就是语言的问题.

Show Comments
备案信息: 京ICP备20002019号