记事本保存文件时易产生 BOM 头,导致织梦 PHP 报"headers already sent"错误。本文详解避免与清理 BOM 的完整方案。
一、BOM 是什么
BOM(Byte Order Mark)是 Unicode 文件开头的字节标记,UTF-8 的 BOM 为 EF BB BF,UTF-16 为 FF FE 或 FE FF。它本身不是可见字符,但 PHP 会将其作为输出内容发送给浏览器。
UTF-8 BOM:EF BB BF (3 bytes)
UTF-16 LE BOM:FF FE (2 bytes)
UTF-16 BE BOM:FE FF (2 bytes)
UTF-16 LE BOM:FF FE (2 bytes)
UTF-16 BE BOM:FE FF (2 bytes)
二、BOM 对织梦的影响
- PHP 报错 "Cannot modify header information - headers already sent"
- 页面顶部出现空白行,影响布局
- RSS、XML 输出失效(BOM 不是合法 XML 字符)
- Cookie、Session 设置失败
- AJAX 返回 JSON 解析失败
注意:Windows 记事本默认 UTF-8 编码必带 BOM,是织梦站点最常见的 BOM 来源。
三、正确保存 GBK 文件的方法
Notepad++
编码 → 转 ANSI → 保存EditPlus
Document → Encoding → 改为 GB2312VSCode
右下角点击 UTF-8 → Save with Encoding → GB2312Sublime
File → Save with Encoding → GB2312四、避免 UTF-8 BOM 的设置
4.1 Notepad++ 配置
设置 → 首选项 → 新建 → 编码 → 选择 "UTF-8(无BOM)"
设置 → 首选项 → 默认目录 → 取消 "使用 BOM"
4.2 VSCode 配置
// settings.json
{
"files.encoding": "gb2312",
"files.autoGuessEncoding": true
}
4.3 PHP 中写入文件时主动去除 BOM
function removeBom($str){
if(substr($str,0,3)===pack('H*','EFBBBF')){
$str=substr($str,3);
}
return $str;
}
$content=removeBom(file_get_contents('template.php'));
五、批量清理 BOM 脚本
5.1 Linux Shell
find /www/wwwroot/yoursite -type f \( -name "*.php" -o -name "*.htm" -o -name "*.html" \) -exec sed -i '1s/^\xEF\xBB\xBF//' {} \;
5.2 PHP 脚本
<?php
function cleanBom($dir){
foreach(glob("$dir/*") as $f){
if(is_dir($f)) { cleanBom($f); continue; }
$ext=pathinfo($f, PATHINFO_EXTENSION);
if(!in_array($ext, ['php','htm','html','txt'])) continue;
$content=file_get_contents($f);
if(substr($content,0,3)===pack('H*','EFBBBF')){
file_put_contents($f, substr($content,3));
echo "清理 BOM: $f\n";
}
}
}
cleanBom('/www/wwwroot/yoursite');
?>
六、常见问题原因分析
6.1 清理后仍报 headers already sent
原因:仅清理 PHP 文件,未清理 include 的 .htm、.txt 模板。
解决:扩展清理范围到所有织梦模板目录。
6.2 文件间歇性出现 BOM
原因:多人协作时不同编辑器设置不一致。
建议:团队统一编辑器与编码设置,并加入 Git Hook 在提交时自动检查 BOM。
七、Git Hook 自动检测
#!/bin/bash
# .git/hooks/pre-commit
exec grep -Il $'\xEF\xBB\xBF' $(git diff --cached --name-only) && {
echo "错误:检测到 BOM,请清理后重新提交"
exit 1
} || exit 0
八、行动指引
建立"BOM 防御体系":编辑器层设置无 BOM 保存,CI 流水线层加入 BOM 检测脚本,部署前执行清理脚本兜底。同时将编码规范写入团队 Wiki,让每个成员理解 BOM 危害,从源头杜绝问题,让织梦站点在 GBK 编码下稳定运行。