打印流
打印流用于方便地输出文本内容。Java 中常见的 System.out 本质上就是一个 PrintStream。
# 1. 核心类
打印流主要包括:
PrintStreamPrintWriter
二者都提供 print、println、printf、format 等方法,可以输出多种类型数据。
# 2. PrintStream
PrintStream 是字节打印流。
try (PrintStream out = new PrintStream("result.txt", StandardCharsets.UTF_8)) {
out.println("hello");
out.printf("score=%d%n", 100);
}
System.out 和 System.err 都是 PrintStream。
System.out.println("normal message");
System.err.println("error message");
# 3. PrintWriter
PrintWriter 是字符打印流,常用于写文本响应、模板结果、日志样式内容。
try (PrintWriter writer = new PrintWriter(
Files.newBufferedWriter(Path.of("result.txt"), StandardCharsets.UTF_8))) {
writer.println("hello");
writer.printf("name=%s, age=%d%n", "Alice", 18);
}
在 Servlet 里经常能看到:
PrintWriter writer = response.getWriter();
writer.println("{\"success\":true}");
# 4. 自动刷新
部分构造方法支持自动刷新。
PrintWriter writer = new PrintWriter(outputStream, true, StandardCharsets.UTF_8);
自动刷新通常发生在调用 println、printf、format 时,而不是每次 write 都刷新。
# 5. 打印流不会直接抛出 IOException
打印流的一个特殊点是很多写入方法不会直接抛出 IOException,而是把异常状态记录下来。
可以通过 checkError() 检查:
writer.println("data");
if (writer.checkError()) {
// handle error
}
这让打印流使用起来方便,但也容易隐藏写入失败。关键业务文件写入不要只依赖打印流。
# 6. PrintStream 和 PrintWriter 的选择
| 场景 | 推荐 |
|---|---|
| 控制台输出 | PrintStream |
| 文本文件输出 | PrintWriter 或 BufferedWriter |
| Web 响应文本 | PrintWriter |
| 二进制数据 | 不使用打印流 |
| 需要严格处理 IOException | BufferedWriter 更明确 |
# 专家实践清单
| 场景 | 是否适合打印流 | 说明 |
|---|---|---|
| 控制台输出 | 适合 | System.out 就是 PrintStream |
| 简单文本响应 | 适合 | Web 响应常见 PrintWriter |
| 严格文件写入 | 谨慎 | 异常处理不够直接 |
| 二进制写入 | 不适合 | 打印流面向文本格式化 |
打印流的定位:
对象/基本值
│ print / println / printf
▼
格式化文本
│ 编码后写出
▼
底层输出流
# Tips 快问快答
Q:打印流主要解决什么问题? A:方便地把基本类型、对象和格式化文本输出到目标流。
Q:PrintStream 和 PrintWriter 区别是什么?
A:前者面向字节输出,后者面向字符输出。
Q:System.out 是什么类型?
A:PrintStream。
Q:打印流适合写二进制文件吗? A:不适合,打印流会进行文本化输出。
Q:打印流异常处理有什么特点?
A:很多方法不会直接抛 IOException,需要通过 checkError 检查。
Q:println 的换行符是否固定?
A:通常使用系统相关换行符。
Q:什么时候优先用 BufferedWriter?
A:需要严格处理文本写入异常和可靠性时。
Q:打印流最大的工程风险是什么? A:方便但容易掩盖异常,不适合关键数据写入链路。
# 7. 总结
打印流的优势是输出方便,适合格式化文本和控制台输出。它不是通用文件写入方案,尤其在需要严格处理异常、保证数据可靠性的场景中,应优先考虑 BufferedWriter、Files 或更明确的输出 API。