【java IO】缓冲流详解

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
相关推荐
爱丽_1 小时前
方法区 / 元空间:JDK 1.7 到 JDK 1.8 到底变了什么?
java·开发语言
JNU freshman2 小时前
Ceph 中与“重构/恢复/回填/重平衡”相关的参数表
java·ceph·重构
寻见9032 小时前
Java为什么能“一次编写,到处运行”?JVM到底解决了什么核心痛点?
java·jvm·java ee
xjdkxnhcoskxbco2 小时前
Java 多线程“八锁”问题深度解析
java·开发语言·多线程
AI克斯2 小时前
【通俗易懂】注解(@)的理解
java
人还是要有梦想的2 小时前
QT的起源
开发语言·qt
spencer_tseng2 小时前
‘<>‘ operator is not allowed for source level below 1.7
java
柏箱2 小时前
文件上传漏洞入门:(upload-labs Pass-1 & Pass-2)
开发语言·前端·javascript
人道领域2 小时前
Day | 07 【苍穹外卖:菜品套餐的缓存】
java·开发语言·redis·缓存击穿·springcache