我正在尝试使用PHP解析CSV文件。
该文件使用逗号作为分隔符,并对包含逗号的字段使用双引号,例如:
foo,"bar, baz",foo2
问题,我面临的问题是我将包含逗号的字段分隔开了。我得到:
"2
rue du ..."
代替:2, rue du ...
。
编码:
该文件似乎不在UTF8中。它的开头有怪异的词句符(apparently not BOM,当从ASCII转换为UTF8:ÿþ
时看起来像这样),并且不显示重音符号。
mb_detect_encoding()
会返回 ASCII 但是无法转换:
mb_convert_encoding()
从ASCII
进行转换,但从UTF-16LE
返回亚洲字符iconv()
返回通知:iconv():错误的字符集,不允许从UTF-16LE
/ ASCII
到UTF8
的转换。 li>
解析:
我尝试使用str_getcsv()
来解析这种单行代码(请参见those 2 comments):
$csv = array_map('str_getcsv', file($file['tmp_name']));
然后我尝试使用fgetcsv()
:
$f = fopen($file['tmp_name'], 'r');
while (($l = fgetcsv($f)) !== false) {
$arr[] = $l;
}
$f = fclose($f);
在两种方式下,我的地址分为两部分。但是,当我尝试此代码示例时,我会正确解析字段:
$str = 'foo,"bar, baz",foo2,azerty,"ban, bal",doe';
$data = str_getcsv($str);
echo '<pre>' . print_r($data, true) . '</pre>';
总结问题:
UTF-16 LE
读取文件,并且开头不显示奇怪的字符) 答案 0 :(得分:1)
我终于自己解决了:
我将文件发送到在线编码检测网站,该网站返回了 UTF16LE 。在检查了什么是 UTF16LE 后,它说它具有 BOM(字节顺序标记)。
我以前的尝试是使用file()
返回文件的 行的数组 ,并使用fopen()
返回资源,但是我们仍然解析 一行 。
我想到的解决方案是转换整个文件(一次一行),而不是分别转换每一行。这是一个可行的解决方案:
$f = file_get_contents($file['tmp_name']); // Get the whole file as string
$f = mb_convert_encoding($f, 'UTF8', 'UTF-16LE'); // Convert the file to UTF8
$f = preg_split("/\R/", $f); // Split it by line breaks
$f = array_map('str_getcsv', $f); // Parse lines as CSV data
我不再用内部逗号分隔地址字段。