outputstreamwriter 的编码行为由关联 charset 的默认 encoder 决定;需自定义错误策略时,应通过 charset.newencoder() 设置 codingerroraction 并手动编码,或包装 outputstream 拦截异常,而非依赖 outputstreamwriter 直接配置。

OutputStreamWriter 本身不直接暴露 CharsetEncoder 的配置接口,但可以通过构造时传入的 Charset 或 CharsetEncoder 实例间接控制编码失败行为。
使用带替换策略的 Charset 构造
最常用方式是通过 Charset.forName("UTF-8").newEncoder() 获取编码器,设置其 malformed input 和 unmappable character 处理策略,再包装成 Charset(需借助 CharsetEncoder + Charset 自定义实现较复杂),更推荐直接用 StandardCharsets 配合 CharsetEncoder 的替代方案:
- 调用
Charset.forName("UTF-8").newEncoder().onUnmappableCharacter(CodingErrorAction.REPLACE) - 但注意:OutputStreamWriter 不接受 encoder,只接受 Charset 或 String 名称
- 因此实际生效的是 Charset 默认的 encoder 行为 —— 多数标准 Charset(如 UTF-8、ISO-8859-1)默认对不可映射字符抛 CharacterCodingException
用 OutputStreamWriter + 自定义 OutputStream 包装异常
若需统一处理(如替换成 ? 或忽略),可在底层 OutputStream 层拦截异常:
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
- 继承 FilterOutputStream,重写
write(byte[], int, int) - 捕获 CharacterCodingException(由内部 encoder 抛出)
- 在 catch 块中写入替代字节(如 UTF-8 中
0xEF 0xBF 0xBD表示 )或跳过 - 再用该 stream 构造 OutputStreamWriter
改用 BufferedWriter + 手动编码(更可控)
绕过 OutputStreamWriter 的自动编码,自己控制编码流程:
- 用
CharsetEncoder encoder = StandardCharsets.UTF_8.newEncoder() - 调用
encoder.onUnmappableCharacter(CodingErrorAction.REPLACE) - 对每个字符串调用
encoder.encode(CharBuffer.wrap(str))得到 ByteBuffer - 将 byte buffer 写入底层 OutputStream
- 配合 BufferedWriter 缓冲写入,避免频繁 flush
推荐做法:优先用 String.getBytes() + try-catch
简单场景下,不必强依赖 OutputStreamWriter 的编码器配置:
- 对要写入的字符串调用
str.getBytes(StandardCharsets.UTF_8) - 该方法内部使用默认 encoder,遇到不可映射字符会抛 UnsupportedEncodingException(实际不会,UTF-8 支持所有 Unicode)
- 但若用
str.getBytes("ISO-8859-1"),则超出范围字符会被静默截断或替换(取决于 JVM 实现) - 更稳妥:用
StandardCharsets.UTF_8.newEncoder().encode(CharBuffer.wrap(str))显式控制
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










