Java IO 从入门到深入(第四篇):缓冲流 Buffered 系列详解(性能优化核心)
在前两篇中,我们已经掌握了:
- 字节流(InputStream / OutputStream)
- 字符流(Reader / Writer)
但是你可能会发现一个问题:
IO 操作很慢
例如:
id="m6tfbf"
逐字节读取文件
性能非常差。
为了解决这个问题,Java 提供了一类非常重要的流:
缓冲流(Buffered Stream)
一、什么是缓冲流?
缓冲流的核心思想:
减少 IO 次数,提高性能
原理:
id="it0d18"
一次读取一大块数据 → 在内存中处理
而不是:
id="j95b38"
每次读取一个字节(频繁访问磁盘)
类比理解
不使用缓冲流:
id="0xbv3b"
每次去超市买一颗米
使用缓冲流:
id="ttz7h7"
一次买一袋米
二、缓冲流分类
缓冲流分为两类:
1 字节缓冲流
id="n7s1p6"
BufferedInputStream
BufferedOutputStream
2 字符缓冲流
id="k5g6sz"
BufferedReader
BufferedWriter
三、BufferedInputStream 使用
示例:
java
import java.io.*;
public class Main {
public static void main(String[] args) throws Exception {
BufferedInputStream bis =
new BufferedInputStream(
new FileInputStream("test.txt")
);
int data;
while((data = bis.read()) != -1){
System.out.print((char)data);
}
bis.close();
}
}
四、BufferedOutputStream 使用
java
BufferedOutputStream bos =
new BufferedOutputStream(
new FileOutputStream("test.txt")
);
bos.write("Hello Buffered IO".getBytes());
bos.close();
为什么 close 很重要?
id="n9y9gq"
close() = flush() + 释放资源
否则:
id="7t7n1t"
数据可能没写入文件
五、BufferedReader 使用(重点)
这是开发中最常用的类之一。
readLine() 方法
java
BufferedReader br =
new BufferedReader(
new FileReader("test.txt")
);
String line;
while((line = br.readLine()) != null){
System.out.println(line);
}
br.close();
特点:
id="p8m6k2"
按行读取
自动处理换行
六、BufferedWriter 使用
java
BufferedWriter bw =
new BufferedWriter(
new FileWriter("test.txt")
);
bw.write("Hello");
bw.newLine();
bw.write("Java IO");
bw.close();
七、缓冲流的底层原理(面试重点)
核心结构:
id="4fxs5k"
byte[] buffer = new byte[8192];
默认缓冲区大小:
id="y2k1ri"
8KB
工作流程
读取:
id="7h7w2v"
磁盘 → buffer → 程序
写入:
id="u0k6kl"
程序 → buffer → 磁盘
为什么更快?
因为:
id="r6ebnp"
减少系统调用次数
对比
不使用缓冲流:
id="k6v3bq"
读1字节 → IO一次
使用缓冲流:
id="v8t5rf"
读8KB → IO一次
八、性能对比示例(经典面试题)
普通字节流复制
java
FileInputStream fis = new FileInputStream("a.jpg");
FileOutputStream fos = new FileOutputStream("b.jpg");
int data;
while((data = fis.read()) != -1){
fos.write(data);
}
使用缓冲流
java
BufferedInputStream bis =
new BufferedInputStream(new FileInputStream("a.jpg"));
BufferedOutputStream bos =
new BufferedOutputStream(new FileOutputStream("b.jpg"));
byte[] buffer = new byte[1024];
int len;
while((len = bis.read(buffer)) != -1){
bos.write(buffer,0,len);
}
bis.close();
bos.close();
👉 性能差距:
id="c7g5mj"
数倍甚至数量级提升
九、推荐最佳实践(非常重要)
最推荐写法:
java
try(
BufferedReader br =
new BufferedReader(
new InputStreamReader(
new FileInputStream("test.txt"), "UTF-8"
)
)
){
String line;
while((line = br.readLine()) != null){
System.out.println(line);
}
}
优点:
id="d6m2jp"
支持编码
支持缓冲
高性能
无乱码
十、缓冲流使用场景
1 大文件读取
id="n0c1ra"
日志文件
数据文件
2 文件复制
id="l3u9m4"
图片 / 视频
3 按行读取文件
id="pj1r3f"
配置文件
日志分析
十一、常见易错点
1 忘记 flush()
id="d8p7m6"
数据丢失
解决:
id="v0u3tt"
flush() 或 close()
2 BufferedReader 不能直接指定编码
错误:
java
new BufferedReader(new FileReader("test.txt"))
问题:
id="9v8zks"
编码不可控
正确:
java
new BufferedReader(
new InputStreamReader(
new FileInputStream("test.txt"), "UTF-8"
)
)
3 混用字节流和字符流
id="y0d7k8"
容易乱码
4 关闭顺序问题
id="d9u6m5"
只需要关闭最外层流
十二、面试高频问题
1 为什么缓冲流更快?
标准答案:
id="6l1j2g"
减少 IO 次数
减少系统调用
2 缓冲区大小是多少?
默认:
id="1q7s2c"
8KB
3 readLine() 会包含换行符吗?
答案:
id="6g5p2z"
不会
4 flush 和 close 区别
| 方法 | 作用 |
|---|---|
| flush | 刷新缓冲区 |
| close | flush + 关闭资源 |
5 为什么推荐 BufferedReader?
id="8h3k9t"
支持 readLine
效率高
使用方便
十三、总结
缓冲流是 Java IO 中:
性能优化的核心组件
核心类:
id="7j2c8r"
BufferedInputStream
BufferedOutputStream
BufferedReader
BufferedWriter
核心优势:
id="p9d3k6"
减少 IO 次数
提升性能
支持按行读取
最推荐组合:
id="k8u1s4"
BufferedReader + InputStreamReader + UTF-8