Java IO 流:从基础原理到实战应用(超完整总结)
下面用清晰、系统、面试+开发都能用的方式,把 Java IO 从头到尾讲透,包括分类、原理、字节流/字符流、缓冲流、转换流、打印流、对象流、文件操作、NIO 简介。
一、先搞懂:什么是 IO?
IO = Input / Output
- Input:从外部(文件、网络、键盘)读入程序内存
- Output:从程序内存写出到外部(文件、网络、控制台)
Java IO 的核心设计思想:
基于流(Stream)的设计 数据像水流一样,按顺序传输,不能回头。
二、IO 流的四大核心分类
1. 按数据方向分
- 输入流(InputStream / Reader) :读数据
- 输出流(OutputStream / Writer) :写数据
2. 按数据单位分
- 字节流(Byte Stream) :以
byte 为单位,万能流
- 顶层父类:
InputStream、OutputStream
- 字符流(Char Stream) :以
char 为单位,专门处理文本
- 顶层父类:
Reader、Writer
3. 按功能分
- 节点流(低级流) :直接连接数据源(文件、数组等)
- 处理流(高级流/包装流) :对节点流包装,增强功能(缓冲、对象序列化等)
三、字节流(万能流)
1. 核心类
- 文件输入:
FileInputStream - 文件输出:
FileOutputStream
2. 适用场景
- 图片、音频、视频、压缩包等二进制文件
- 任何文件都能用(文本也可以,但容易乱码)
3. 基础用法(复制文件标准模板)
try (
FileInputStream in = new FileInputStream("a.jpg");
FileOutputStream out = new FileOutputStream("b.jpg");
) {
byte[] buf = new byte[1024 * 8];
int len;
while ((len = in.read(buf)) != -1) {
out.write(buf, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
}
读到
-1 表示文件结束。
四、字符流(专门处理文本)
1. 核心类
- 文件读取:
FileReader - 文件写入:
FileWriter
2. 特点
- 以字符为单位,自动处理编码
- 只适合纯文本文件
3. 基础用法
try (
FileReader fr = new FileReader("a.txt");
FileWriter fw = new FileWriter("b.txt");
) {
char[] cbuf = new char[1024];
int len;
while ((len = fr.read(cbuf)) != -1) {
fw.write(cbuf, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
}
五、缓冲流(提高性能,开发必用)
对普通流包装,减少磁盘 IO,速度大幅提升。
1. 字节缓冲流
-
BufferedInputStream -
BufferedOutputStream
2. 字符缓冲流
-
BufferedReader:独有 readLine() 读一行 -
BufferedWriter:独有 newLine() 换行
3. 字符缓冲流实战(按行读写)
try (
BufferedReader br = new BufferedReader(new FileReader("in.txt"));
BufferedWriter bw = new BufferedWriter(new FileWriter("out.txt"));
) {
String line;
while ((line = br.readLine()) != null) {
bw.write(line);
bw.newLine();
}
} catch (IOException e) {
e.printStackTrace();
}
六、转换流(解决编码乱码神器)
核心类
-
InputStreamReader:字节流 → 字符流 -
OutputStreamWriter:字符流 → 字节流
作用
指定编码读写(UTF-8、GBK 等),彻底解决乱码。
// 用 GBK 读取
InputStreamReader isr = new InputStreamReader(
new FileInputStream("gbk.txt"), "GBK");
// 用 UTF-8 写出
OutputStreamWriter osw = new OutputStreamWriter(
new FileOutputStream("utf8.txt"), "UTF-8");
七、打印流(方便输出)
核心类
-
PrintStream(字节) -
PrintWriter(字符)
特点:
- 不会抛 IO 异常
- 有
print() / println() 方法 - 常用:
System.out 就是 PrintStream
PrintWriter pw = new PrintWriter("log.txt");
pw.println("Hello");
pw.println(123);
pw.close();
八、对象流(序列化与反序列化)
作用
把 Java 对象写入文件/网络,或从文件读取对象。
核心类
-
ObjectOutputStream:序列化(写对象) -
ObjectInputStream:反序列化(读对象)
要求
类必须实现 Serializable 接口。
// 写对象
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("user.dat"))) {
User user = new User("张三", 20);
oos.writeObject(user);
}
// 读对象
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("user.dat"))) {
User user = (User) ois.readObject();
}
九、标准 IO 实战案例
1. 复制任意文件(字节缓冲流)
try (
BufferedInputStream in = new BufferedInputStream(new FileInputStream("src.mp4"));
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream("dest.mp4"));
) {
byte[] buf = new byte[8192];
int len;
while ((len = in.read(buf)) != -1) {
out.write(buf, 0, len);
}
}
2. 读取文本并统计行数
int count = 0;
try (BufferedReader br = new BufferedReader(new FileReader("test.txt"))) {
while (br.readLine() != null) count++;
}
System.out.println("总行数:" + count);
3. 按编码复制文本(解决乱码)
try (
BufferedReader br = new BufferedReader(
new InputStreamReader(new FileInputStream("a.txt"), "GBK"));
BufferedWriter bw = new BufferedWriter(
new OutputStreamWriter(new FileOutputStream("b.txt"), "UTF-8"));
) {
String line;
while ((line = br.readLine()) != null) {
bw.write(line);
bw.newLine();
}
}
十、IO 流体系总表(记忆神器)
| 分类 | 输入流 | 输出流 | 作用 |
|---|---|---|---|
| 字节节点流 | FileInputStream | FileOutputStream | 读写任意文件 |
| 字符节点流 | FileReader | FileWriter | 读写文本 |
| 字节缓冲流 | BufferedInputStream | BufferedOutputStream | 提高字节流速度 |
| 字符缓冲流 | BufferedReader | BufferedWriter | 按行读写,高性能文本 |
| 转换流 | InputStreamReader | OutputStreamWriter | 编码转换、解决乱码 |
| 对象流 | ObjectInputStream | ObjectOutputStream | 对象序列化 |
| 打印流 | / | PrintStream/PrintWriter | 方便打印输出 |
十一、IO 关闭原则(非常重要)
- 从外到内关闭
- JDK7+ 推荐 try-with-resources 实现
AutoCloseable 接口的流会自动关闭,不用手动 close()
十二、BIO、NIO、AIO 简单区别
- BIO(传统 IO) :阻塞流,一个连接一个线程
- NIO(Java 4+) :非阻塞、面向缓冲区、多路复用
- AIO(Java 7+) :异步非阻塞,基于事件和回调
日常文件读写用 BIO 足够;高并发网络编程用 NIO。
十三、面试高频考点
- 字节流和字符流区别
- flush() 和 close() 的关系
- 缓冲流为什么快
- 序列化注意事项
- try-with-resources 原理
- 如何解决 IO 乱码
如果你需要,我可以继续给你:
- 一套 Java IO 常考面试题+标准答案
- 一份 IO 流实战作业(含答案)
- 或者 从 BIO 到 NIO 的完整进阶教程
你想要哪个?