BOM是文件开头用于标识编码的特殊字节,UTF-8中为EF BB BF;XML解析时易因BOM误读报“前言中不允许有内容”错误;安全读取需先探测再跳过BOM,推荐用BOMInputStream或手动跳过,避免FileReader;生成XML时应显式指定UTF-8编码以防写入BOM。

BOM(Byte Order Mark,字节顺序标记)是加在文本文件开头的一组特殊字节,用于标识文件的编码方式。对UTF-8来说,BOM是固定的三个字节 EF BB BF;虽然UTF-8本身不依赖字节序,但这个标记可被解析器用来明确识别“这是UTF-8编码”,不过XML规范其实不推荐在UTF-8 XML中使用BOM——因为部分解析器(如Dom4j、JDOM、Xerces等)会把BOM误读为文档内容,导致报错“Content is not allowed in prolog”。
XML解析时BOM引发的典型错误
常见现象包括:
- 解析器报错:第一行出现乱码字符(如
),或直接提示“前言中不允许有内容” - 用十六进制工具(如UltraEdit、xxd)查看文件开头,可见
ef bb bf(UTF-8 BOM)或ff fe(UTF-16LE)、fe ff(UTF-16BE) - 用
FileReader这类默认编码读取时失败——因为它不识别BOM,会把BOM当普通字符读入
Java中安全读取带BOM的XML文件
核心思路是:先探测BOM,再按实际编码读取,跳过BOM字节。推荐以下几种方式:
-
用Apache Commons IO的
BOMInputStream(最稳妥):
它自动检测并跳过BOM,并通过getBOMCharsetName()返回真实编码名,后续可传给InputStreamReader -
手动探测+跳过:用
FileInputStream读前3字节,判断是否为EF BB BF;若是,构造new UTF8Encoding(false).getString(buffer, 3, len-3)(.NET风格)或用new String(bytes, 3, bytes.length-3, "UTF-8")(Java) -
避免用
FileReader:它不支持BOM处理,且依赖系统默认编码,极易出错;一律改用InputStreamReader配合明确指定的Charset
生成XML时避免写入BOM
如果你用Java写XML文件(比如用Transformer、DOM或JAXB输出),默认不会写BOM——但某些Windows编辑器(如记事本)另存为UTF-8时会自动添加。防范措施:
- 用
OutputStreamWriter写入时,显式指定StandardCharsets.UTF_8(Java 7+),它不会写BOM - 若必须兼容旧工具,可用
Files.write(path, content.getBytes(StandardCharsets.UTF_8), StandardOpenOption.CREATE),同样无BOM - 避免用
FileWriter——它不接受编码参数,行为不可控
快速验证与修复脚本(命令行辅助)
开发中可快速确认和清理BOM:
- 检查BOM:
file -i your.xml或hexdump -C your.xml | head -n 1 - 移除BOM(Linux/macOS):
tail -c +4 your.xml > no_bom.xml(跳过前3字节) - 批量清理(Python一行):
for f in *.xml; do sed -i '1s/^\xEF\xBB\xBF//' "$f"; done










