java中inputstreamreader默认不跳过utf-8 bom(0xef 0xbb 0xbf),会将其解码为ufeff干扰字符串处理;推荐做法是手动检测跳过、使用apache commons io的bominputstream自动剥离,或从源头避免写入bom。

Java 中 InputStreamReader 默认不会自动跳过 UTF-8 文件的 BOM(Byte Order Mark,0xEF 0xBB 0xBF),它会把 BOM 当作普通字符读取为 uFEFF(零宽无间断空格),可能干扰后续字符串处理(如 JSON 解析、trim 判断、正则匹配等)。
UTF-8 BOM 的本质和影响
UTF-8 的 BOM 并非必需,只是三个字节 EF BB BF。Java 的 InputStreamReader 按照编码规则将其解码为 Unicode 字符 uFEFF,该字符在字符串开头时肉眼不可见,但 str.charAt(0) 或 str.startsWith("...") 会出错。
手动跳过 BOM 的推荐做法
在创建 InputStreamReader 后,立即检查并跳过首个字符(如果它是 uFEFF):
- 用
InputStream包装原始输入流(如FileInputStream) - 先用
InputStream读取前 3 字节,判断是否为EF BB BF;若是,跳过这 3 字节再构造InputStreamReader - 或更通用:用
InputStreamReader读一个char,如果是uFEFF且位于开头,就忽略它
使用 Apache Commons IO 简化处理
借助 org.apache.commons.io.input.BOMInputStream 可自动剥离 BOM:
- 它包装任意
InputStream,在读取时透明跳过 UTF-8/UTF-16/UTF-32 的 BOM - 构造
InputStreamReader时传入它,无需额外判断逻辑 - 示例:
new InputStreamReader(new BOMInputStream(fis), StandardCharsets.UTF_8)
避免 BOM 的源头治理
最稳妥的方式是从文件生成端避免写入 BOM:
- 编辑器(如 VS Code、IntelliJ)保存时选择 “UTF-8 without BOM”
- 构建工具(如 Maven 插件、Gradle)写文件时显式指定不带 BOM 的编码
- 程序生成文本文件时,用
Files.write(path, lines, StandardCharsets.UTF_8)—— Java 7+ 的此方法默认不写 BOM
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











