OutputStreamWriter本身不提供设置UnmappableCharacterAction的API,需通过CharsetEncoder显式配置:获取Charset、调用newEncoder()、用onUnmappableCharacter()设定IGNORE/REPLACE/REPORT策略,再传入构造器;推荐JDK7+用Files.newBufferedWriter封装更安全。

OutputStreamWriter 本身不直接提供设置 UnmappableCharacterAction 的 API,这个行为由它底层封装的 CharsetEncoder 控制,而标准构造器无法暴露该配置。要实现对非法字符(如 Unicode 无法映射到目标编码的字符)的自定义处理(比如忽略、替换或报错),必须手动构建带指定编码器策略的 OutputStreamWriter。
使用 CharsetEncoder 显式配置 UnmappableCharacterAction
核心思路是:先获取目标 Charset,调用其 newEncoder() 创建编码器,再通过 onUnmappableCharacter() 设置策略,最后用该编码器构造 OutputStreamWriter。
- IGNORE:跳过无法映射的字符(静默丢弃)
-
REPLACE:替换成
?或其他默认替代符(取决于编码器) -
REPORT:遇到非法字符时抛出
CharacterCodingException
示例(写入 GBK 时忽略无法表示的 Unicode 字符):
OutputStream os = new FileOutputStream("out.txt");
Charset charset = Charset.forName("GBK");
CharsetEncoder encoder = charset.newEncoder()
.onUnmappableCharacter(CodingErrorAction.IGNORE);
OutputStreamWriter writer = new OutputStreamWriter(os, encoder);
注意 REPLACEMENT 与编码器默认替换符的关系
REPLACE 行为不总是输出 ?,它依赖编码器自身的替换逻辑。例如:
- UTF-8 编码器在
REPLACE模式下通常生成(U+FFFD) - GBK 编码器可能用
?或空格代替,具体由 JVM 实现决定 - 若需统一替换为指定字符(如
'*'),需自行包装Writer或改用Charset.encode()手动处理
避免踩坑:不要用 String.getBytes() + OutputStream
常见误区是先用 str.getBytes("GBK") 再写入 OutputStream,这会绕过 CharsetEncoder 的错误处理机制,导致 UnsupportedEncodingException 或静默截断。正确做法始终是让 OutputStreamWriter 或 CharsetEncoder 统一负责编码和错误策略。
替代方案:用 Files.newBufferedWriter(推荐 JDK7+)
更简洁安全的方式是使用 NIO.2:
Charset charset = StandardCharsets.UTF_8; // 或其他
CharsetEncoder encoder = charset.newEncoder()
.onUnmappableCharacter(CodingErrorAction.REPLACE);
Path path = Paths.get("out.txt");
try (Writer writer = Files.newBufferedWriter(path, encoder)) {
writer.write("Hello\u0000World"); // \u0000 在某些编码中不可映射
}
它内部仍基于 OutputStreamWriter,但封装更好,资源管理更可靠。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











