PHP处理竖线分隔CSV(值含逗号)首行解析异常的解决方法
解决竖线分隔CSV首行解析异常的问题
问题场景
我有一个竖线分隔的CSV文件,存储名言数据,示例内容如下:
The old world is dying, and a new world struggles to be born; now is the time of monsters.|Antonio Gramsci|1891-1937
The unexamined life is not worth living.|Socrates|c.469-399 B.C.
使用以下PHP代码读取并转换为数组时,首行未被正确分割,第二行解析正常:
<?php $file = fopen("quotes.csv", "r"); $data = fgetcsv($file, 1000, "|"); $arr = []; while (($data = fgetcsv($file, 1000, "|")) !== false) { $arr[] = $data; } echo "<pre>";print_r($arr) ?>
首行输出结果(未正确分割):
[0] => Array ( [0] => The old world is dying, and a new world struggles to be born; now is the time of monsters.|Antonio Gramsci|1891-1937| )
第二行输出结果(正常解析):
[1] => Array ( [0] => The unexamined life is not worth living. [1] => Socrates [2] => c.469-399 B.C. )
已知首行异常与第一列包含逗号有关,需要实现首行的正确解析,使其输出与第二行一致。
问题根源与修复步骤
1. 移除多余的fgetcsv调用
代码开头先调用了一次fgetcsv读取首行,但未将其存入数组,后续while循环从第二行开始读取。这会导致首行数据丢失(你的输出显示首行在数组中,可能是代码粘贴失误)。删除这行多余调用,确保所有行都能进入循环处理。
2. 处理UTF-8 BOM(如果存在)
若CSV文件是UTF-8编码且带有BOM头(文件开头的EF BB BF字节),fgetcsv会将BOM作为第一个字段的一部分,导致分隔符|无法被正确识别。需在读取文件前跳过BOM。
3. 显式设置enclosure参数
默认情况下fgetcsv使用双引号作为字段包裹符,即使字段未被引号包裹,字段内的逗号仍可能触发错误解析逻辑。显式设置enclosure为空字符串,可强制fgetcsv完全按照指定的|分隔符分割字段。
修复后的完整代码
<?php $file = fopen("quotes.csv", "r"); $arr = []; // 跳过UTF-8 BOM(如果存在) $bom = fread($file, 3); if ($bom !== "\xEF\xBB\xBF") { rewind($file); } while (($data = fgetcsv($file, 1000, "|", "")) !== false) { // 清理行尾多余|导致的空字段 $data = array_filter($data, function($value) { return $value !== ""; }); $arr[] = $data; } echo "<pre>"; print_r($arr); fclose($file); ?>
关键说明
- 移除多余调用后,所有行都会被循环读取处理;
- 跳过BOM确保文件开头的特殊字符不会干扰分隔符识别;
- 空字符串的
enclosure参数强制fgetcsv忽略字段内的逗号,仅按|分割; array_filter用于清理行尾多余|产生的空字段,保证数组结构一致。
内容的提问来源于stack exchange,提问作者Carlo M
相关产品推荐
相关产品推荐

