You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

fgetcsv返回字符串长度异常,正则匹配失效求解决

问题:fgetcsv读取CSV返回字符串长度异常,正则匹配失败

我正在开发一个简单脚本,用于从CSV文件读取URL并执行正则匹配,但正则模式始终匹配失败。仔细排查后发现异常:fgetcsv返回的字符串经var_dump()输出的长度完全不符合实际。

示例代码

$read = fopen("input.csv","r");
while($data = fgetcsv($read,null,",","\"","\\")){
    var_dump($data[0]);
    echo mb_detect_encoding($data[0]);
    echo "\n";
}

输出结果

string(25) "/index.html"
ASCII
string(23) "/login.html"
ASCII
string(15) "/insta/"
ASCII

CSV文件中的字符串与返回的内容一致,但显示的长度明显错误。这是什么原因?是否存在无法看见的隐形字符?或是特殊编码问题?该如何解决?


原因分析

问题出在**UTF-8 BOM(字节顺序标记)**上。你的CSV文件开头带有三个不可见的字节(EF BB BF),也就是UTF-8 BOM。虽然mb_detect_encoding检测结果显示为ASCII,但BOM字节会被算入字符串长度中:

  • 第一个字符串"/index.html"实际长度是22,但显示为25,多出来的3个字节就是BOM的长度;
  • 后续行没有BOM,长度相对正常,但第一行的隐形字符会直接导致正则匹配失败。

解决方案

1. 手动去除CSV文件的BOM

用文本编辑器(如Notepad++)打开CSV文件,选择「编码」→「UTF-8无BOM」,保存即可彻底解决问题。

2. 在PHP代码中处理BOM

可以在读取文件时跳过BOM,或者对读取到的字符串做清理:

方式一:读取时跳过BOM

$read = fopen("input.csv","r");
// 读取前3个字节判断是否是UTF-8 BOM
$bom = fread($read, 3);
if ($bom !== "\xEF\xBB\xBF") {
    // 不是BOM则把指针移回开头
    fseek($read, 0);
}
while($data = fgetcsv($read,null,",","\"","\\")){
    var_dump($data[0]);
    echo mb_detect_encoding($data[0]);
    echo "\n";
}
fclose($read);

方式二:清理字符串中的BOM

$read = fopen("input.csv","r");
while($data = fgetcsv($read,null,",","\"","\\")){
    // 去除字符串开头的BOM
    $url = preg_replace('/^\x{FEFF}/u', '', $data[0]);
    var_dump($url);
    echo mb_detect_encoding($url);
    echo "\n";
}
fclose($read);

3. 使用file_get_contents配合str_getcsv(可选)

如果CSV文件不大,可以先读取整个文件并去除BOM,再解析:

$content = file_get_contents("input.csv");
// 去除BOM
$content = preg_replace('/^\x{FEFF}/u', '', $content);
$rows = str_getcsv($content, "\n");
foreach ($rows as $row) {
    $data = str_getcsv($row);
    var_dump($data[0]);
}

内容的提问来源于stack exchange,提问作者Gedi Nixan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 23:45:41