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”。
常见现象包括:
),或直接提示“前言中不允许有内容”ef bb bf(UTF-8 BOM)或ff fe(UTF-16LE)、fe ff(UTF-16BE)FileReader这类默认编码读取时失败——因为它不识别BOM,会把BOM当普通字符读入核心思路是:先探测BOM,再按实际编码读取,跳过BOM字节。推荐以下几种方式:
BOMInputStream(最稳妥):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
如果你用Java写XML文件(比如用Transformer、DOM或JAXB输出),默认不会写BOM——但某些Windows编辑器(如记事本)另存为UTF-8时会自动添加。防范措施:
OutputStreamWriter写入时,显式指定StandardCharsets.UTF_8(Java 7+),它不会写BOMFiles.write(path, content.getBytes(StandardCharsets.UTF_8), StandardOpenOption.CREATE),同样无BOMFileWriter——它不接受编码参数,行为不可控开发中可快速确认和清理BOM:
file -i your.xml 或 hexdump -C your.xml | head -n 1
tail -c +4 your.xml > no_bom.xml(跳过前3字节)for f in *.xml; do sed -i '1s/^\xEF\xBB\xBF//' "$f"; done