PrintStream侧重便捷输出与自动换行/类型转换,OutputStreamWriter负责字节到字符的编码桥接;前者处理“怎么写”,后者把控“写成什么编码”。

Java中打印流(PrintStream)和转换流(OutputStreamWriter)是控制文本输出格式的两大核心工具:前者侧重便捷输出与自动换行/类型转换,后者负责字节到字符的编码桥接。用好它们的关键在于明确分工——PrintStream处理“怎么写”,OutputStreamWriter把控“写成什么编码”。
PrintStream:简化输出,兼顾格式与容错
PrintStream封装了底层输出流(如System.out本质就是PrintStream实例),支持直接打印基本类型、字符串甚至对象(调用toString),且不抛出IOException(内部捕获并设置错误标志)。它默认使用平台默认编码,适合快速调试或控制台输出。
- 启用自动刷新:构造时传入true,例如new PrintStream(out, true),每次println()后立即刷出,避免缓冲导致内容延迟显示
- 重定向标准输出:用System.setOut(new PrintStream("log.txt"))可将所有System.out.println转向文件,常用于日志捕获
- 注意null安全:print(null)输出字符串"null"而非报错,但若需严格校验,应自行判空
OutputStreamWriter:精准控制字符编码与换行符
当需要指定UTF-8、GBK等编码,或跨平台统一换行格式(如强制用"\n"而非系统默认的"\r\n")时,OutputStreamWriter不可替代。它把字符按指定编码转为字节,再交给底层OutputStream。
- 显式声明编码:推荐用new OutputStreamWriter(out, StandardCharsets.UTF_8),避免依赖系统默认编码引发乱码
- 组合BufferedWriter提升性能:包装后使用write() + newLine()可精确控制每行结尾,例如Windows下写"\n"而非自动补"\r\n"
- 及时关闭释放资源:OutputStreamWriter本身不自动刷新,务必调用close()或配合try-with-resources确保缓冲区内容写出
混合使用场景:日志文件带时间戳与编码保障
实际开发中常需二者协作——比如向UTF-8编码的日志文件写入带格式的时间戳消息:
立即学习“Java免费学习笔记(深入)”;
- 用FileOutputStream打开文件,传给OutputStreamWriter并指定UTF_8编码
- 再用PrintWriter(PrintStream的字符版,功能类似)包装它,获得printf()等格式化能力
- 示例:try (PrintWriter pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream("app.log"), UTF_8))) { pw.printf("[%s] INFO: %s%n", Instant.now(), "User logged in"); }
避坑提醒:常见格式异常根源
中文乱码、换行失效、内容不显示等问题,多源于流链配置不当:
- 未指定编码 → 使用OutputStreamWriter时漏掉Charset参数,导致写入字节与读取解码不一致
- 忘记刷新或关闭 → 缓冲区未满时内容滞留内存,程序结束前丢失最后几行
- 混用PrintStream与Writer → 同一文件被两个流同时写入,可能造成内容交错或覆盖



















