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:
立即学习“Java免费学习笔记(深入)”;
- 它包装任意
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


















