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)。
代码示例(按行读取文本文件)
importjava.io.BufferedReader;importjava.io.FileReader;importjava.io.IOException;publicclassBufferedReaderDemo{publicstaticvoidmain(String[] args){// 推荐使用 try-with-resources 自动关闭流(Java 7+)try(BufferedReader br =newBufferedReader(newFileReader("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
代码示例(高效写入文本文件)
importjava.io.BufferedWriter;importjava.io.FileWriter;importjava.io.IOException;publicclassBufferedWriterDemo{publicstaticvoidmain(String[] args){try(BufferedWriter bw =newBufferedWriter(newFileWriter("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(控制台输出的核心实现)。
代码示例(控制台/文件输出)
importjava.io.FileOutputStream;importjava.io.PrintStream;publicclassPrintStreamDemo{publicstaticvoidmain(String[] args){// 1. 控制台输出(System.out 是 PrintStream 实例)PrintStream consoleOut =System.out; consoleOut.println("打印整数:"+123); consoleOut.printf("格式化输出:姓名=%s,年龄=%d\n","张三",25);// 2. 写入文件(字节流方式)try(PrintStream fileOut =newPrintStream(newFileOutputStream("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 更适配文本场景。
代码示例(文本文件格式化输出)
importjava.io.PrintWriter;publicclassPrintWriterDemo{publicstaticvoidmain(String[] args){// try-with-resources 自动关闭流try(PrintWriter pw =newPrintWriter("printwriter.txt",true)){// autoFlush=true:println/printf 触发自动刷新 pw.println("打印对象:"+newObject());// 自动调用 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)提升性能:

// 手动指定缓冲区大小为 65536 字符(64KB)BufferedReader br =newBufferedReader(newFileReader("bigfile.txt"),65536);

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

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

PrintWriter pw =newPrintWriter("test.txt"); pw.println("测试数据");if(pw.checkError()){thrownewRuntimeException("写入文件失败");// 手动抛出业务异常兜底} 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 格式化输出),兼顾效率与易用性。

Read more

Java处理JSON编程实用技巧

Java处理JSON编程实用技巧

1. 前言 JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于阅读和编写,同时也易于机器解析和生成。在Java开发中,JSON处理是一项非常常见且重要的任务。本文将详细介绍Java中处理JSON的各种实用技巧,包括主流JSON框架的使用、性能优化以及最佳实践。 本文将重点介绍Gson、Jackson和Fastjson这三个主流Java JSON处理库的使用技巧和性能优化方法。 2. JSON处理框架对比 Java生态中有多个优秀的JSON处理框架,每个框架都有其特点和适用场景。下面是三个主流框架的对比: 3. Gson使用技巧 3.1 基础用法 Gson是Google开发的Java库,用于将Java对象转换为JSON表示,以及将JSON字符串转换回等效的Java对象。 3.1.1 Maven依赖 <dependency> <groupId>com.google.code.gson</groupId> <artifactId>

By Ne0inhk
【JAVA 进阶】Spring Cloud 微服务全栈实践:从认知到落地

【JAVA 进阶】Spring Cloud 微服务全栈实践:从认知到落地

本文采用“总—分—总”结构,围绕 Spring Cloud 在微服务架构中的核心能力进行系统讲解。以理论为主、代码为辅,提供清晰多级目录与落地建议,适合已有 Spring Boot 基础、准备或正在进行微服务实践的工程师。 文章目录 * 1. 总览与定位 * 1.1 微服务背景与挑战 * 1.2 Spring Cloud 生态与版本矩阵 * 1.3 微服务能力全景图 * 2. 服务注册与发现 * 2.1 核心概念与术语 * 2.2 组件对比:Eureka / Consul / Nacos * 2.3 快速实践:Eureka Server 搭建 * 2.4

By Ne0inhk
C语言代码优化与性能调优:编译器优化、内存优化、算法优化与工具链配合

C语言代码优化与性能调优:编译器优化、内存优化、算法优化与工具链配合

C语言代码优化与性能调优:编译器优化、内存优化、算法优化与工具链配合 一、前言:为什么代码优化与性能调优是C语言开发的进阶技能? 学习目标 * 理解代码优化的本质:通过优化代码结构和算法,提高程序的执行效率 * 理解性能调优的本质:通过分析程序的运行时间和资源消耗,定位和修复性能瓶颈 * 明确代码优化与性能调优的重要性:提高程序的执行效率、节省资源、提升用户体验 * 掌握本章学习重点:编译器优化、内存优化、算法优化、工具链配合、避坑指南、实战案例分析 * 学会使用优化技术和工具链调优C语言程序 重点提示 💡 代码优化与性能调优是C语言开发的进阶技能!通过优化和调优,你可以提高程序的执行效率,节省资源,提升用户体验。 二、模块1:编译器优化——利用编译器提高程序效率 2.1 学习目标 * 理解编译器优化的本质:通过编译器的优化选项,自动优化代码 * 掌握gcc的优化选项:-O0、-O1、-O2、-O3、-Os、-Ofast * 掌握编译器优化的避坑指南:

By Ne0inhk
【从0开始学习Java | 第23篇】动态代理

【从0开始学习Java | 第23篇】动态代理

文章目录 * Java动态代理概述 * 一、动态代理的核心概念 * 形象解释 * 二、两种主流动态代理实现 * 1. JDK动态代理(基于接口) * 原理 * 示例代码 * 优缺点 * 2. CGLIB动态代理(基于子类) * 原理 * 示例代码(需引入CGLIB依赖) * 优缺点 * 三、JDK与CGLIB动态代理对比 * 四、实际应用场景 * 五、总结 Java动态代理概述 在Java开发中,代理模式设计模式之一,而动态代理作为代理模式的进阶形式,在框架开发(如Spring AOP)、日志记录、权限控制等场景中发挥着关键作用。本文将从核心概念出发,拆解两种主流动态代理的实现逻辑,并分析其适用场景。 一、动态代理的核心概念 动态代理指在程序运行时,通过反射机制动态生成代理类,而非在编译期预先定义。其核心价值在于:无需为每个目标类手动编写代理类,即可统一为多个目标类添加横切逻辑(如日志、事务、异常处理),降低代码耦合度。

By Ne0inhk