一、IO 流进阶核心(缓冲流 + 转换流)
(一)缓冲流(Buffered 系列)
1. 核心定位与原理
- 定位 :高级处理流,通过包装基础流实现性能极致优化,是处理大文件的首选。
- 核心原理 :底层内置固定大小的缓冲区(8192 字节 = 8KB) ,读取时一次性从磁盘读取缓冲区大小的数据存入内存,写入时先将数据存入缓冲区,缓冲区满或手动刷新时再一次性写入磁盘,大幅减少磁盘 IO 次数。
2. 字节缓冲流(BufferedInputStream / BufferedOutputStream)
构造方法
表格
| 构造方法 | 完整说明 |
|---|---|
BufferedInputStream(InputStream in) |
使用默认缓冲区大小(8192 字节),包装任意字节输入基础流(如 FileInputStream) |
BufferedInputStream(InputStream in, int size) |
自定义缓冲区大小,包装任意字节输入基础流 |
BufferedOutputStream(OutputStream out) |
使用默认缓冲区大小,包装任意字节输出基础流(如 FileOutputStream) |
BufferedOutputStream(OutputStream out, int size) |
自定义缓冲区大小,包装任意字节输出基础流 |
核心方法(继承自基础流,无特有方法)
- 读取:
read()、read(byte[] b)、read(byte[] b, int off, int len) - 写入:
write(int b)、write(byte[] b)、write(byte[] b, int off, int len) - 刷新:
flush()(强制将缓冲区数据写入磁盘,字节缓冲流底层无强制缓冲,但若自定义缓冲区需手动刷新) - 关闭:
close()(关闭最外层流,底层自动关闭被包装的基础流)
实操注意事项
- 无需修改基础流的调用逻辑,仅需在创建基础流后,用缓冲流包装即可。
- 适用于所有类型文件(图片、音频、视频、文本),是文件复制的最优选择。
3. 字符缓冲流(BufferedReader / BufferedWriter)
构造方法
表格
| 构造方法 | 完整说明 |
|---|---|
BufferedReader(Reader in) |
默认缓冲区大小,包装任意字符输入基础流(如 FileReader、InputStreamReader) |
BufferedReader(Reader in, int sz) |
自定义缓冲区大小,包装任意字符输入基础流 |
BufferedWriter(Writer out) |
默认缓冲区大小,包装任意字符输出基础流(如 FileWriter、OutputStreamWriter) |
BufferedWriter(Writer out, int sz) |
自定义缓冲区大小,包装任意字符输出基础流 |
特有核心方法
表格
| 流类型 | 方法名 | 完整功能说明 | 返回值 | 终止条件 |
|---|---|---|---|---|
BufferedReader |
readLine() |
读取一整行文本,自动忽略换行符,仅获取行内有效数据 | String |
读到文件末尾返回 null |
BufferedWriter |
newLine() |
写入跨平台换行符,自动适配 Windows(\r\n)、Linux(\n)、Mac(\r) |
void |
无 |
常规方法
- 继承自
Reader/Writer:read()、read(char[] cbuf)、write(int c)、write(char[] cbuf)、write(String str)、write(String str, int off, int len) - 刷新与关闭:
flush()(必须调用,否则缓冲区数据无法写入磁盘)、close()
(二)转换流(InputStreamReader / OutputStreamWriter)
1. 核心定位与本质
- 定位 :字节流与字符流的唯一桥梁,解决 "字节流读取文本乱码" 和 "手动指定字符集" 的核心问题。
- 本质 :
转换流 = 字节流 + 字符集,底层将字节流的字节数据,按指定字符集解码为字符(输入),或将字符按指定字符集编码为字节(输出)。
2. 构造方法(含字符集重载
表格
| 流类型 | 构造方法 | 完整说明 |
|---|---|---|
InputStreamReader |
InputStreamReader(InputStream in) |
用系统默认字符集,将字节输入流转换为字符输入流 |
InputStreamReader |
InputStreamReader(InputStream in, String charsetName) |
用指定字符集 (如 "UTF-8"、"GBK"),转换字节输入流 |
InputStreamReader |
InputStreamReader(InputStream in, Charset cs) |
用 Charset 类指定字符集,转换字节输入流 |
OutputStreamWriter |
OutputStreamWriter(OutputStream out) |
用系统默认字符集,将字节输出流转换为字符输出流 |
OutputStreamWriter |
OutputStreamWriter(OutputStream out, String charsetName) |
用指定字符集,转换字节输出流 |
OutputStreamWriter |
OutputStreamWriter(OutputStream out, Charset cs) |
用 Charset 类指定字符集,转换字节输出流 |
3. 核心方法
- 完全继承
Reader/Writer的所有方法,无特有方法。 - 核心价值:在字节流场景下,精准控制字符编码,彻底避免乱码。
4. 核心使用场景
- 数据源是字节流(如网络 Socket 流、文件字节流),但需要按字符处理文本数据。
- 读取 / 写入的文本文件编码格式与系统默认编码不一致(如系统默认 GBK,文件是 UTF-8)。
二、打印流(PrintStream / PrintWriter)
1. 核心定位与核心特点
- 定位 :专门用于输出数据 的高级流,是 Java 中最便捷的输出工具,替代传统
write方法的繁琐。 - 三大核心特点 :
- 只写不读:仅操作输出目的地,不处理数据源。
- 原样输出 :打印任意数据类型(
int、boolean、Object等),均按字符串形式原样写入 (如打印97,写入"97",而非 ASCII 字符'a')。 - 异常处理简化 :底层已处理
IOException,无需显式捕获(仅需通过checkError()方法判断是否出错)。
2. 字节打印流(PrintStream)
构造方法
表格
| 构造方法 | 完整说明 |
|---|---|
PrintStream(File file) |
关联本地文件,使用系统默认字符集 |
PrintStream(File file, String csn) |
关联本地文件,指定字符集 |
PrintStream(String fileName) |
关联文件路径,使用系统默认字符集 |
PrintStream(String fileName, String csn) |
关联文件路径,指定字符集 |
PrintStream(OutputStream out) |
包装字节输出基础流 |
PrintStream(OutputStream out, boolean autoFlush) |
包装字节输出基础流,指定是否自动刷新 |
PrintStream(OutputStream out, boolean autoFlush, String encoding) |
包装字节输出基础流,指定自动刷新和字符集 |
成员方法
(1)特有打印方法(核心)
表格
| 方法名 | 完整功能 | 换行 / 刷新 |
|---|---|---|
print(Xxx xx) |
打印任意类型数据(int、String、Object 等),不换行、不刷新 |
否 |
println(Xxx xx) |
打印任意类型数据,自动换行、自动刷新 | 是 |
printf(String format, Object... args) |
格式化打印,支持占位符(%s、%d、%f 等) |
否 |
format(String format, Object... args) |
与 printf 功能完全一致,格式化打印 |
否 |
(2)常规方法
write(int b):按字节写入(非原样输出,需注意)。checkError():判断输出过程中是否出现错误,返回boolean。close():关闭流,释放资源。
关键细节
- 字节打印流底层无缓冲区 ,
autoFlush参数开启与否,不影响println方法的自动刷新。
3. 字符打印流(PrintWriter)
构造方法
表格
| 构造方法 | 完整说明 |
|---|---|
PrintWriter(File file) |
关联本地文件,系统默认字符集 |
PrintWriter(File file, Charset charset) |
关联本地文件,指定字符集 |
PrintWriter(String fileName) |
关联文件路径,系统默认字符集 |
PrintWriter(String fileName, Charset charset) |
关联文件路径,指定字符集 |
PrintWriter(Writer out) |
包装字符输出基础流 |
PrintWriter(Writer out, boolean autoFlush) |
包装字符输出基础流,指定是否自动刷新 |
PrintWriter(OutputStream out) |
包装字节输出基础流,系统默认字符集 |
PrintWriter(OutputStream out, boolean autoFlush) |
包装字节输出基础流,指定自动刷新 |
PrintWriter(OutputStream out, boolean autoFlush, Charset charset) |
包装字节输出基础流,指定自动刷新和字符集 |
成员方法
- 与
PrintStream完全一致:print()、println()、printf()、format()、write()、checkError()、close()。
关键细节(核心差异)
- 字符打印流底层有缓冲区 ,必须满足以下两个条件之一,才能实现自动刷新:
- 构造时开启
autoFlush = true; - 调用
println()、printf()、format()方法(print()方法不触发刷新)。
- 构造时开启
- 若未开启自动刷新,需手动调用
flush()方法,否则数据会滞留缓冲区。
三、序列化流 / 反序列化流(Object 系列)
1. 核心定位与概念
- 序列化 :将 Java 对象转换为字节序列,写入文件 / 网络,实现对象的持久化存储或网络传输。
- 反序列化:将文件 / 网络中的字节序列,还原为 Java 对象。
- 核心组件 :
ObjectOutputStream(序列化流)、ObjectInputStream(反序列化流)。
2. 核心构造方法
表格
| 流类型 | 构造方法 | 完整说明 |
|---|---|---|
ObjectOutputStream |
ObjectOutputStream(OutputStream out) |
包装字节输出基础流,创建序列化流,用于写入对象 |
ObjectInputStream |
ObjectInputStream(InputStream in) |
包装字节输入基础流,创建反序列化流,用于读取对象 |
3. 核心成员方法
表格
| 流类型 | 方法名 | 完整功能 | 异常说明 |
|---|---|---|---|
ObjectOutputStream |
writeObject(Object obj) |
将指定对象序列化,写入底层流 | 若对象未实现 Serializable,抛 NotSerializableException |
ObjectInputStream |
readObject() |
从底层流读取字节序列,反序列化为对象 | 若类不兼容、文件损坏,抛 InvalidClassException / EOFException |
4. 核心前提与强制规则
(1)对象序列化的强制前提
被序列化的 JavaBean 类,必须实现 java.io.Serializable 接口。
- 该接口是标记接口,无任何抽象方法,仅用于标识 "此类对象可被序列化"。
- 若未实现,调用
writeObject()时直接抛出NotSerializableException。
(2)类版本兼容规则(serialVersionUID)
- 问题 :序列化后,若修改了 JavaBean 类(如添加 / 删除成员变量),反序列化时会抛出
InvalidClassException。 - 解决方案 :在 JavaBean 类中,手动添加固定的序列化版本号 (
serialVersionUID),确保类版本一致。 - 格式 :
private static final long serialVersionUID = 固定长整型数值;(如1L、123456789L)。
(3)成员变量的序列化控制
表格
| 关键字 | 作用 | 反序列化结果 |
|---|---|---|
transient(瞬态) |
修饰成员变量,使其不参与序列化 | 该变量值为默认值 (int 为 0,String 为 null) |
static(静态) |
静态成员变量不参与序列化 | 反序列化时,获取当前类的静态变量值(非序列化时的值) |
(4)其他关键细节
- 序列化的对象数据,不能手动修改(如用记事本打开编辑),否则反序列化会失败。
- 若对象包含其他对象类型的成员变量,该成员变量的类也必须实现
Serializable接口。 - 反序列化时,必须保证项目中存在该对象的类(类路径、类名一致)。
四、解压缩流(Zip 系列)
1. 核心定位与核心对象
- 定位 :专门用于处理 ZIP 格式压缩包的高级流,实现文件 / 文件夹的压缩与解压。
- 核心对象 :
ZipEntry------ 代表压缩包中的每一个文件或文件夹,包含该条目名称、大小、是否为目录等信息。
2. 解压流(ZipInputStream)
核心作用
读取 ZIP 压缩包中的数据,遍历所有 ZipEntry,将其还原为本地文件 / 文件夹。
构造方法
表格
| 构造方法 | 完整说明 |
|---|---|
ZipInputStream(InputStream in) |
包装字节输入基础流(如 FileInputStream),读取压缩包 |
ZipInputStream(InputStream in, Charset charset) |
包装字节输入基础流,指定字符集(解决压缩包内中文文件名乱码) |
核心方法
表格
| 方法名 | 完整功能 | 返回值 | 终止条件 |
|---|---|---|---|
getNextEntry() |
读取压缩包中的下一个 ZipEntry,并将流定位到该条目开头 |
ZipEntry |
遍历完所有条目,返回 null |
closeEntry() |
关闭当前 ZipEntry,将流定位到下一个条目开头 |
void |
无 |
read(byte[] b) |
读取当前 ZipEntry 的数据(字节) |
int |
读到该条目末尾,返回 -1 |
close() |
关闭解压流,释放资源 | void |
无 |
解压核心流程
- 创建
FileInputStream关联 ZIP 压缩包。 - 创建
ZipInputStream包装FileInputStream(指定字符集,解决中文乱码)。 - 定义
ZipEntry变量,通过getNextEntry()遍历压缩包中所有条目。 - 对每个
ZipEntry进行判断:- 若为目录:通过
File类的mkdirs()创建对应目录。 - 若为文件:创建对应父目录,再通过
FileOutputStream+ 缓冲流,将ZipInputStream中的数据写入本地文件。
- 若为目录:通过
- 每个条目处理完成后,调用
closeEntry()关闭当前条目。 - 遍历结束后,关闭
ZipInputStream。
3. 压缩流(ZipOutputStream)
核心作用
将本地文件 / 文件夹,封装为 ZipEntry,写入 ZIP 压缩包。
构造方法
表格
| 构造方法 | 完整说明 |
|---|---|
ZipOutputStream(OutputStream out) |
包装字节输出基础流(如 FileOutputStream),写入压缩包 |
ZipOutputStream(OutputStream out, Charset charset) |
包装字节输出基础流,指定字符集(解决压缩包内中文文件名乱码) |
核心方法
表格
| 方法名 | 完整功能 |
|---|---|
putNextEntry(ZipEntry e) |
向压缩包中添加一个 ZipEntry,并将流定位到该条目开头 |
closeEntry() |
关闭当前 ZipEntry,准备添加下一个条目 |
write(byte[] b, int off, int len) |
将文件数据写入当前 ZipEntry |
setLevel(int level) |
设置压缩级别(0-9,0 为无压缩,9 为最高压缩,默认 5) |
close() |
关闭压缩流,释放资源 |
压缩核心流程
- 创建
FileOutputStream关联要生成的 ZIP 压缩包。 - 创建
ZipOutputStream包装FileOutputStream(指定字符集)。 - 递归遍历本地要压缩的文件 / 文件夹:
- 对每个文件 / 文件夹,创建对应的
ZipEntry(注意条目名称的路径层级)。 - 调用
putNextEntry()将ZipEntry写入压缩包。 - 若为文件:通过
FileInputStream+ 缓冲流,将文件数据写入ZipOutputStream。 - 调用
closeEntry()关闭当前条目。
- 对每个文件 / 文件夹,创建对应的
- 遍历结束后,关闭
ZipOutputStream。
五、第三方 IO 工具包(Commons-io + Hutool)
(一)Apache Commons-io 工具包
1. 核心定位与引入步骤
- 定位 :Apache 开源的轻量级 IO 专用工具包,封装了所有底层 IO 流、File 类的复杂操作,彻底消除重复代码。
- 引入步骤(本地项目) :
- 创建项目根目录下的
lib文件夹。 - 将
commons-io-x.x.x.jar复制到lib文件夹。 - 右键 jar 包 →
Add as Library→ 选择项目模块 → 确认,完成依赖引入。
- 创建项目根目录下的
2. 核心工具类与全量方法
(1)FileUtils(文件 / 文件夹操作核心)
表格
| 方法名 | 完整功能说明 |
|---|---|
copyFile(File srcFile, File destFile) |
复制单个文件,自动处理流的创建与关闭 |
copyFile(File srcFile, File destFile, boolean preserveFileDate) |
复制单个文件,指定是否保留文件最后修改时间 |
copyDirectory(File srcDir, File destDir) |
复制整个文件夹(含所有子文件、子目录) |
copyDirectory(File srcDir, File destDir, FileFilter filter) |
复制文件夹,按过滤器筛选要复制的内容 |
copyDirectoryToDirectory(File srcDir, File destDir) |
将源文件夹整体复制到目标文件夹下(作为子文件夹) |
deleteDirectory(File directory) |
删除整个文件夹(含所有内容),自动递归删除子文件 / 目录 |
cleanDirectory(File directory) |
清空文件夹内所有内容,保留文件夹本身 |
readFileToString(File file, Charset encoding) |
按指定字符集,读取文件内容为字符串 |
readFileToByteArray(File file) |
读取文件内容为字节数组(适用于非文本文件) |
readLines(File file, Charset encoding) |
按指定字符集,逐行读取文件,返回 List<String> |
write(File file, CharSequence data, Charset encoding) |
按指定字符集,将字符串写入文件(覆盖原内容) |
write(File file, CharSequence data, Charset encoding, boolean append) |
按指定字符集,将字符串写入文件(指定是否续写) |
writeLines(File file, Collection<?> lines, Charset encoding) |
将集合中的元素,逐行写入文件(覆盖原内容) |
writeLines(File file, Collection<?> lines, Charset encoding, boolean append) |
将集合中的元素,逐行写入文件(指定是否续写) |
sizeOf(File file) |
获取文件 / 文件夹的大小(文件夹大小为所有子文件大小之和) |
(2)IOUtils
表格
| 方法名 | 完整功能说明 |
|---|---|
copy(InputStream input, OutputStream output) |
复制字节流数据(适用于文件复制、流转发) |
copy(InputStream input, OutputStream output, int bufferSize) |
复制字节流数据,指定缓冲区大小 |
copyLarge(InputStream input, OutputStream output) |
复制大文件(超过 2GB)的字节流数据 |
copy(Reader input, Writer output) |
复制字符流数据 |
readLines(InputStream input, Charset encoding) |
按指定字符集,读取字节流数据为 List<String> |
readLines(Reader input) |
读取字符流数据为 List<String> |
toString(InputStream input, Charset encoding) |
按指定字符集,将字节流数据转换为字符串 |
write(String data, OutputStream output, Charset encoding) |
按指定字符集,将字符串写入字节输出流 |
close(Closeable closeable) |
关闭实现 Closeable 接口的资源(流、File 等),底层处理空指针和异常 |
(二)Hutool 工具包
1. 核心定位
- 国产全能型 Java 工具包,IO 模块是其核心功能之一,封装比 Commons-io 更简洁,中文文档完善,支持更多实用功能。
2. IO 核心工具类与全量功能
表格
| 类名 | 完整功能定位 | 核心方法(代表性) |
|---|---|---|
IoUtil |
流操作工具类,对应 Commons-io 的 IOUtils |
copy(InputStream in, OutputStream out)、readUtf8(InputStream in)、write(OutputStream out, String content, Charset charset)、close(AutoCloseable... closeables) |
FileUtil |
文件操作工具类,对应 Commons-io 的 FileUtils,功能更全面 |
copy(File src, File dest)、del(File file)、readString(File file, Charset charset)、writeString(File file, String content, Charset charset)、mkdirs(File file)、listFiles(File dir, FileFilter filter) |
FileTypeUtil |
文件类型判断工具,通过文件头判断真实类型(不受后缀名欺骗) | getFileType(File file)、getFileType(String path) |
WatchMonitor |
文件 / 目录监听工具,实时监控文件的创建、修改、删除 | createAll(File dir, Watcher watcher)、createModify(File dir, Watcher watcher) |
ClassPathResource |
类路径资源访问工具,便捷读取 src/main/resources 下的文件 |
getStream()、readString()、getFile() |
FileReader |
Hutool 封装的文件读取器,简化字符读取 | readLine()、readLines()、readString() |
FileWriter |
Hutool 封装的文件写入器,简化字符写入 | write(String content)、append(String content)、writeLines(Collection<?> lines) |
3. 核心优势
- 方法名更符合中文开发习惯(如
del()替代deleteDirectory())。 - 自动适配字符集(默认 UTF-8),减少编码错误。
- 支持自动关闭资源(基于
try-with-resources底层封装)。