PHP读取文件时JSON解析失败或headers already sent错误多因UTF-8 BOM(0xEF 0xBB 0xBF)导致,可用ltrim($content, "\xEF\xBB\xBF")清除后分割,或fopen+fgets跳过BOM逐行读取,源头应保存为UTF-8 without BOM。

PHP读取文件时遇到json_decode失败或headers already sent错误
大概率是文件开头存在UTF-8 BOM(Byte Order Mark),即三个不可见字节 0xEF 0xBB 0xBF。它不会在编辑器里显示,但会干扰json_decode、include、HTTP头输出等操作。尤其当用记事本保存为UTF-8后,BOM几乎必然存在。
直接file_get_contents再explode或preg_split,BOM会混进第一行内容里,比如$lines[0]实际是"\xEF\xBB\xBF第一行",导致字符串比较、正则匹配全部失效。
用ltrim清除BOM后再按行分割
这是最轻量、兼容性最好的方案:不依赖外部库,不重读文件,不改变原始换行符逻辑。
-
file_get_contents读取整个文件后,用ltrim($content, "\xEF\xBB\xBF")去掉开头BOM(仅去开头,不影响中间的\xEF字符) - 再用
preg_split('/\r\n|\r|\n/', $content, -1, PREG_SPLIT_NO_EMPTY)安全分割——比explode("\n", ...)更鲁棒,能统一处理Windows/macOS/Linux换行 - 注意不要用
trim,它会同时删首尾空白,可能误删有意义的空行或缩进
用fopen+fgets逐行读取并跳过BOM
适合大文件,避免内存爆满;也能在第一行就识别并跳过BOM,后续行不受影响。
立即学习“PHP免费学习笔记(深入)”;
- 先
fopen打开文件,fgets($fp, 4)读前4字节,检查是否为"\xEF\xBB\xBF",是则fseek($fp, 3, SEEK_CUR)跳过 - 之后循环
fgets,每行自然不含BOM,可直接trim或正则处理 - 注意
fgets保留末尾换行符,如需干净字符串,得rtrim($line, "\r\n") - 别用
file()函数——它内部不做BOM检测,返回的数组首元素仍带BOM
写入文件前主动避免BOM产生
很多问题其实源于源头:用IDE(如VS Code、PhpStorm)保存PHP/JSON/配置文件时,默认编码选“UTF-8 with BOM”,必须手动改成“UTF-8 without BOM”。
- PHP脚本自身若含BOM,会导致
headers already sent——连session_start()都会失败 - 生成JSON文件时,用
file_put_contents($path, json_encode($data, JSON_UNESCAPED_UNICODE), LOCK_EX),确保内容纯JSON,不拼接任何额外字符 - 如果必须用
echo输出JSON给前端,开头加header('Content-Type: application/json; charset=utf-8');,并确认PHP文件本身无BOM
ltrim($s, "\xEF\xBB\xBF"),比事后调试json_last_error_msg()省半小时。











