Java IO 核心:BufferedReader/BufferedWriter & PrintStream/PrintWriter 技术笔记

Java IO 核心:BufferedReader/BufferedWriter & PrintStream/PrintWriter 技术笔记

一、笔记概述

本文聚焦 Java IO 体系中高频使用的 4 个字符/字节流工具类(BufferedReader、BufferedWriter、PrintStream、PrintWriter),从核心定位、功能差异、适用场景、代码示例、拓展技巧五个维度拆解,帮助理解其设计逻辑与实际应用,解决"该用哪个流写/读数据"的核心问题。

二、核心定位与设计目标

这 4 个类分为两大阵营,核心设计目标差异显著:

1. 缓冲流阵营(BufferedReader + BufferedWriter)

属于 Java IO 底层高效字符流,核心目标是提升字符读写效率。通过内置字符缓冲区减少磁盘/网络 IO 次数(避免每次读写都触发底层硬件操作),是处理文本文件"基础且高效"的核心工具,偏底层、偏严谨。

2. 打印流阵营(PrintStream + PrintWriter)

属于 Java IO 上层易用型流,核心目标是便捷地格式化输出数据。屏蔽了繁琐的 IO 异常处理,支持所有基本数据类型(int、double、boolean 等)和对象的直接打印,还提供格式化输出(printf),是面向"业务输出、日志打印、控制台展示"的易用工具,偏上层、偏实用。

三、逐个拆解:功能、示例、适用场景

1. BufferedReader(字符缓冲输入流)

核心功能
  • 包装底层字符输入流(如 FileReader),通过缓冲区提升文本读取效率;
  • 提供核心方法 readLine(),可直接按行读取文本(返回一行字符串,null 表示读取完毕),解决了"手动拼接字符读行"的繁琐;
  • 所有 IO 操作都会抛出 IOException,必须手动处理(try-catch 或 throws)。
代码示例(按行读取文本文件)
java 复制代码
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class BufferedReaderDemo {
    public static void main(String[] args) {
        // 推荐使用 try-with-resources 自动关闭流(Java 7+)
        try (BufferedReader br = new BufferedReader(new FileReader("demo.txt"))) {
            String line;
            // 核心:readLine() 按行读取,一行一个字符串
            while ((line = br.readLine()) != null) {
                System.out.println("读取到内容:" + line);
            }
        } catch (IOException e) {
            // 必须处理异常:打印异常信息或做业务兜底
            System.err.println("读取文件失败:" + e.getMessage());
            e.printStackTrace();
        }
    }
}
适用场景
  • 高效读取大文本文件(如日志文件、配置文件、CSV 文件);
  • 需要按行处理文本内容的场景(如解析行式数据、统计文件行数);
  • 控制台输入读取(new BufferedReader(new InputStreamReader(System.in)))。

2. BufferedWriter(字符缓冲输出流)

核心功能
  • 包装底层字符输出流(如 FileWriter),通过缓冲区减少写入次数,提升文本写入效率;
  • 提供 newLine() 方法,自动适配不同操作系统的换行符(Windows 是 \r\n,Linux 是 \n);
  • 仅支持字符/字符串的写入(write() 方法),无格式化能力,所有操作抛出 IOException
代码示例(高效写入文本文件)
java 复制代码
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;

public class BufferedWriterDemo {
    public static void main(String[] args) {
        try (BufferedWriter bw = new BufferedWriter(new FileWriter("output.txt"))) {
            // 写入字符串
            bw.write("Java IO 缓冲流示例");
            // 换行(适配系统)
            bw.newLine();
            // 写入字符数组
            char[] chars = "BufferedWriter 高效写入".toCharArray();
            bw.write(chars);
            // 手动刷新缓冲区(确保数据写入磁盘,close() 也会自动刷新)
            bw.flush();
        } catch (IOException e) {
            System.err.println("写入文件失败:" + e.getMessage());
            e.printStackTrace();
        }
    }
}
适用场景
  • 高频次写入文本数据(如批量生成文本文件、写入大量日志片段);
  • 对写入性能有要求,且仅需基础字符串/字符写入的场景;
  • 需要适配多系统换行符的跨平台文本写入。

3. PrintStream(字节打印流)

核心功能
  • 处理字节流的格式化输出工具,底层基于字节操作;
  • 支持 print()/println()/printf() 方法,可直接打印所有基本数据类型(int、double 等)和对象(自动调用 toString());
  • 屏蔽 IO 异常(内部捕获,不向外抛出),可通过 checkError() 方法判断是否写入失败;
  • 支持自动刷新(构造时指定 autoFlush=true),System.out 本质就是 PrintStream(控制台输出的核心实现)。
代码示例(控制台/文件输出)
java 复制代码
import java.io.FileOutputStream;
import java.io.PrintStream;

public class PrintStreamDemo {
    public static void main(String[] args) {
        // 1. 控制台输出(System.out 是 PrintStream 实例)
        PrintStream consoleOut = System.out;
        consoleOut.println("打印整数:" + 123);
        consoleOut.printf("格式化输出:姓名=%s,年龄=%d\n", "张三", 25);

        // 2. 写入文件(字节流方式)
        try (PrintStream fileOut = new PrintStream(new FileOutputStream("printstream.txt"), true)) {
            // autoFlush=true:调用 println/printf 时自动刷新缓冲区
            fileOut.println("打印布尔值:" + true);
            fileOut.printf("浮点格式化:%.2f\n", 3.1415);
            // 检查是否有错误
            if (fileOut.checkError()) {
                System.err.println("写入文件出错");
            }
        } // 无需处理 IO 异常(PrintStream 内部捕获)
    }
}
适用场景
  • 控制台输出(System.out/System.err);
  • 字节流场景下的格式化输出(如网络字节流、二进制文件中嵌入文本);
  • 不想处理 IO 异常,追求快速输出的简单场景。

4. PrintWriter(字符打印流)

核心功能
  • 处理字符流的格式化输出工具,是 PrintStream 的"字符版",更适合文本处理;
  • 功能与 PrintStream 几乎一致:支持 print/println/printf、屏蔽 IO 异常、自动刷新;
  • 可直接包装字符流(如 FileWriter),也可包装字节流(底层自动转换),比 PrintStream 更适配文本场景。
代码示例(文本文件格式化输出)
java 复制代码
import java.io.PrintWriter;

public class PrintWriterDemo {
    public static void main(String[] args) {
        // try-with-resources 自动关闭流
        try (PrintWriter pw = new PrintWriter("printwriter.txt", true)) {
            // autoFlush=true:println/printf 触发自动刷新
            pw.println("打印对象:" + new Object()); // 自动调用 toString()
            pw.printf("日期格式化:%tF %<tT\n", System.currentTimeMillis());
            pw.print("null 处理:");
            pw.println(null); // 打印字符串 "null",不抛空指针
        } // 无需处理 IO 异常
    }
}
适用场景
  • 文本文件的格式化输出(日志生成、报表打印);
  • 字符流场景下的业务输出(如 Web 响应流、字符型网络通信);
  • 追求易用性,需要快速打印多种数据类型的场景(替代 BufferedWriter + 手动类型转换)。

四、核心区别

1. 缓冲流 vs 打印流(核心阵营差异)

  • 异常处理:缓冲流(BufferedReader/BufferedWriter)所有操作抛出 IOException,必须手动处理;打印流(PrintStream/PrintWriter)内部捕获异常,不向外抛出,仅通过 checkError() 检查。
  • 功能侧重:缓冲流仅专注"高效读写字符",无格式化能力,仅支持字符/字符串操作;打印流侧重"格式化输出",支持所有数据类型,提供 println/printf 等便捷方法。
  • 底层类型:缓冲流仅处理字符流,必须包装 Reader/Writer 子类;PrintStream 处理字节流,PrintWriter 处理字符流(可兼容字节流)。

2. PrintStream vs PrintWriter(打印流内部差异)

  • 底层操作:PrintStream 基于字节,PrintWriter 基于字符;
  • 文本适配:PrintWriter 更适合纯文本处理(换行、字符编码适配更友好),PrintStream 更适合字节流场景(如控制台、二进制文件);
  • 编码处理:PrintWriter 构造时可直接指定字符编码,PrintStream 需通过 OutputStreamWriter 间接指定,文本场景下 PrintWriter 更易用。

3. BufferedReader vs BufferedWriter(缓冲流内部差异)

  • 读写方向:BufferedReader 是输入流(读数据),核心方法 readLine();BufferedWriter 是输出流(写数据),核心方法 write()/newLine();
  • 操作逻辑:两者均依赖缓冲区,Reader 是"读入缓冲区再处理",Writer 是"写入缓冲区再刷盘",都需手动 flush(或 close)确保数据生效。

五、拓展技巧 & 最佳实践

1. 流的关闭:优先使用 try-with-resources

Java 7+ 提供的 try-with-resources 语法可自动关闭实现 AutoCloseable 接口的流,无需手动调用 close(),避免资源泄漏。所有 4 个类都支持该语法,是生产环境的首选。

2. 性能优化:缓冲流的缓冲区大小

默认情况下,BufferedReader/BufferedWriter 的缓冲区是 8192 字符(8KB),若处理超大文件,可手动指定更大的缓冲区(如 64KB)提升性能:

java 复制代码
// 手动指定缓冲区大小为 65536 字符(64KB)
BufferedReader br = new BufferedReader(new FileReader("bigfile.txt"), 65536);

3. 异常兜底:打印流的错误检查

PrintStream/PrintWriter 不抛异常,但需通过 checkError() 检查写入是否失败,避免"写入失败但程序无感知":

java 复制代码
PrintWriter pw = new PrintWriter("test.txt");
pw.println("测试数据");
if (pw.checkError()) {
    throw new RuntimeException("写入文件失败"); // 手动抛出业务异常兜底
}
pw.close();

4. 选型口诀(快速决策)

  • 读文本、要高效、按行读 → 用 BufferedReader;
  • 写文本、要高效、纯字符 → 用 BufferedWriter;
  • 打日志、控制台、格式化、不想处理异常 → 用 PrintWriter(文本)/PrintStream(字节);
  • 跨平台换行、高频写 → 优先 BufferedWriter + newLine();
  • 多数据类型输出、快速开发 → 优先 PrintWriter。

六、总结

  1. BufferedReader/BufferedWriter 是"底层高效读写工具",偏性能、需处理异常,适合对 IO 效率有要求的文本读写场景;
  2. PrintStream/PrintWriter 是"上层易用打印工具",偏便捷、屏蔽异常,适合格式化输出、日志打印、控制台展示等场景;
  3. 文本处理优先选字符流(BufferedReader/BufferedWriter/PrintWriter),字节流场景(如控制台、二进制文件)选 PrintStream;
  4. 实际开发中,常组合使用(如 BufferedReader 读数据 + PrintWriter 格式化输出),兼顾效率与易用性。
相关推荐
Aric_Jones2 小时前
idea使用.env运行SpringBoot项目
java·spring boot·intellij-idea
刘一说2 小时前
Java 中实现多租户架构:数据隔离策略与实践指南
java·oracle·架构
beata2 小时前
Java基础-9:深入 Java 虚拟机(JVM):从底层源码到核心原理的全面解析
java·后端
SimonKing2 小时前
分享一款可以管理本地端口的IDEA插件:Port Manager
java·后端·程序员
索荣荣2 小时前
Maven配置文件(pom.xml)终极指南
java·开发语言
第七序章2 小时前
【Linux学习笔记】初识Linux —— 理解gcc编译器
linux·运维·服务器·开发语言·人工智能·笔记·学习
代码栈上的思考2 小时前
SpringBoot 拦截器
java·spring boot·spring
-Springer-2 小时前
STM32 学习 —— 个人学习笔记5(EXTI 外部中断 & 对射式红外传感器及旋转编码器计数)
笔记·stm32·学习
送秋三十五2 小时前
一次大文件处理性能优化实录————Java 优化过程
java·开发语言·性能优化