Java基础全套教程(八)—— IO流核心详解
Java基础全套教程(八)—— IO流核心详解
在Java企业级开发中,此前学习的集合、数组仅能实现内存级临时数据存储,程序重启、断电后数据会彻底丢失。而实际业务中,大量场景需要实现数据持久化存储、跨设备数据交互,例如本地文件读写、日志落地、配置文件解析、网络数据传输、文件批量同步、对象持久化保存等。
支撑所有程序与外部设备数据交互的核心技术就是Java IO流。IO流是Java数据持久化、文件操作、网络通信、框架底层IO模型的核心基础,几乎所有中间件、框架的底层数据传输均依赖IO思想实现。本章将从零深度拆解IO流全套体系,包含核心概念、分类架构、底层原理、全套流实战、设计模式、企业级避坑规范、面试重难点,全程贴合企业开发标准,补齐IO所有底层机制与高频考点。
本章学习目标
-
深度理解IO输入输出核心定义、数据流向规则、数据源分类,彻底分清读写方向,杜绝流向混淆问题;
-
吃透Java IO三大分类维度、四大顶层抽象父类的设计规范与底层通用原理,建立完整IO知识体系;
-
熟练掌握节点流、缓冲流、转换流、打印流、数据流、对象流的特性、适用场景与实战用法;
-
掌握File文件类全套操作,厘清File类与IO流的职责边界,实现文件完整读写管理流程;
-
精通IO装饰器模式底层原理,理解处理流包装增强节点流的核心机制;
-
掌握序列化与反序列化底层机制、版本兼容规则、高频坑点与企业级解决方案;
-
彻底解决中文乱码、流资源泄露、文件覆盖、读写异常、大文件IO性能瓶颈等核心问题;
-
掌握Apache Commons-IO工具类高阶用法,熟练使用企业极简IO开发规范,提升代码健壮性与开发效率。
8.1 IO流核心基础概念
8.1.1 IO的核心定义与核心准则
IO是**Input(输入)和Output(输出)**的缩写,是Java程序与外部数据源进行数据交互、数据传输的核心技术体系,所有原生IO操作API全部封装在java.io核心包中。
核心必考准则(终身不变):IO所有读写方向,仅以JVM程序内存为唯一参照标准,与外部文件、设备、网络无关,这是区分输入、输出流的核心依据,也是新手最容易混淆的知识点。
-
输入Input(读):外部数据源 → 程序内存,核心行为:读取外部数据到程序中;
-
输出Output(写):程序内存 → 外部数据源,核心行为:将程序数据写出落地。
8.1.2 数据源分类与职责划分
数据源是IO流操作的载体,是所有数据的存储媒介,开发中常见数据源包含:本地文件、内存数组、网络端口、数据库、硬件设备、控制台等。根据数据流向可分为两类:
-
源设备:数据提供者,为程序提供读取数据的来源,对应所有输入流,只能读不能写;
-
目标设备:数据接收存储者,接收程序写出的数据,对应所有输出流,只能写不能读。
8.1.3 流的核心特性与底层本质
流(Stream)是IO的核心抽象概念,可通俗理解为数据传输的虚拟管道,用于串联程序与外部数据源,实现数据连续传输。流的底层本质是有序、单向、字节/字符序列数据流,具备三大核心特性:
-
单向传输:输入流只能读、输出流只能写,管道方向固定,无法双向切换;
-
顺序读写:数据严格按照传输顺序读取、写入,无法随机跳跃读写(随机访问流除外);
-
资源独占性:IO流属于系统资源,开启后会占用文件句柄、内存资源,必须手动关闭,否则会造成资源泄露、文件占用、程序卡顿等问题。
核心开发规范:JDK7+ 强制使用 try-with-resource 语法,自动关闭流资源,彻底规避资源泄露问题。
8.2 IO流整体分类体系(核心分类逻辑)
Java IO流体系庞大,但所有流均可通过三大核心维度精准划分,无例外、无重叠,掌握该分类逻辑即可快速匹配所有业务场景,是精通IO流的核心前提。
8.2.1 按数据传输方向分类
该分类决定流的核心功能(读/写),衍生IO四大顶层父类:
-
输入流:负责读取外部数据到程序,顶层父类:
InputStream(字节)、Reader(字符); -
输出流:负责程序数据写出到外部,顶层父类:
OutputStream(字节)、Writer(字符)。
8.2.2 按数据处理单元分类(开发最常用)
该分类决定流的适配文件类型,是开发选型、面试高频考点:
1. 字节流
以1字节(8bit)为最小操作单元,是计算机数据的通用存储单元。可处理电脑中所有格式文件,包含文本、图片、视频、音频、压缩包、二进制文件等。所有字节流命名统一以 Stream 结尾。
2. 字符流
以字符为最小操作单元,内置编码解码机制,专门适配纯文本文件(txt、java、md、properties等),无法处理图片、视频等二进制媒体文件。所有字符流命名统一以 Reader/Writer 结尾。
核心底层区别:字节流直接操作原始二进制数据;字符流=字节流+编码解码缓冲区,专门解决文本中文乱码问题。
8.2.3 按流的功能层级分类
该分类决定流的能力层级,是IO功能拓展的核心:
1. 节点流(基础流)
底层基础流,可直接对接数据源/目标设备,直接完成读写操作,是所有IO操作的底层支撑。代表:文件流、数组流。功能单一、读写效率低。
2. 处理流(包装流)
不直接对接数据源,仅用于包装节点流,基于装饰器模式动态增强基础流功能,例如缓存提速、按行读取、编码转换、对象序列化等。企业开发优先使用处理流,性能与灵活性远超节点流。
8.3 IO四大核心抽象父类(体系根基)
InputStream、OutputStream、Reader、Writer 是Java IO体系的四大顶层抽象类,所有IO流实现类均直接或间接继承这四个类,统一了所有流的通用方法与操作规范,是IO体系的根基。
8.3.1 字节流抽象父类
InputStream(字节输入流)
所有字节输入流的顶层抽象父类,无法实例化,定义了字节读取的通用核心方法:
-
int read():读取单个字节,返回字节ASCII码值,读取到文件末尾返回-1(核心终止条件);
-
int read(byte[] b):批量读取字节到数组,返回实际读取的字节长度,无数据返回-1;
-
void close():关闭流,释放系统文件句柄与内存资源。
OutputStream(字节输出流)
所有字节输出流的顶层抽象父类,定义了字节写出通用规范:
-
void write(int b):写出单个字节数据;
-
void write(byte[] b):批量写出字节数组全部数据;
-
void write(byte[] b,int off,int len):写出数组指定区间数据(企业高频,避免冗余空数据);
-
void flush():刷新缓冲区,强制将内存缓存数据落地到外部设备;
-
void close():关闭输出流资源,关闭前自动刷新缓冲区。
8.3.2 字符流抽象父类
Reader(字符输入流)
所有字符输入流顶层父类,专为文本读取设计,操作单元为字符,方法与字节输入流高度一致:
-
int read():读取单个字符,返回Unicode编码,末尾返回-1;
-
int read(char[] cbuf):批量读取字符到字符数组,返回实际读取长度;
-
void close():关闭字符流资源。
Writer(字符输出流)
所有字符输出流顶层父类,是字符流核心优势所在,支持直接操作字符串:
-
void write(int c):写入单个字符;
-
void write(char[] cbuf):批量写入字符数组;
-
void write(String str):字符流独有核心方法,直接写入字符串,无需字节转换;
-
flush()/close():刷新缓冲区、关闭资源。
核心易错点:字符流自带缓冲区,不执行flush/close,数据会滞留内存,无法落地到文件。
8.4 基础文件节点流实战(IO底层核心)
文件流是开发中最常用的节点流,直接对接本地文件数据源,是所有文件IO操作的底层基础,分为文件字节流、文件字符流两类,适配不同文件场景。
8.4.1 文件字节流(通用全类型文件读写)
FileInputStream/FileOutputStream是基础文件字节流,支持电脑所有格式文件读写,无文件类型限制,是媒体文件、二进制文件操作的唯一基础流。
核心特性:无编码问题、通用所有文件、读写效率低(无缓存)、单字节读写频繁消耗磁盘IO。
关键知识点:FileOutputStream 默认覆盖原有文件内容,构造方法传入 true 开启追加模式。
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* 文件字节流实战:通用文件读写、图片无损复制
* 底层原理:二进制字节读写,适配所有文件类型
* 避坑点:批量读取必须使用有效长度len,避免写入空字节
*/
public class FileByteStreamDemo {
public static void main(String[] args) {
readTextFile();
writeFileContent();
copyImageFile();
}
// 字节流读取任意文件
public static void readTextFile() {
// try-with-resource 自动关闭流,杜绝资源泄露
try (FileInputStream fis = new FileInputStream("test.txt")) {
// 自定义字节缓冲区,批量读写,减少IO次数
byte[] buffer = new byte[1024];
int len;
StringBuilder sb = new StringBuilder();
// 循环读取:len=-1 读取完毕
while ((len = fis.read(buffer)) != -1) {
// 只拼接有效字节数据,避免缓冲区空数据
sb.append(new String(buffer, 0, len));
}
System.out.println("文件读取内容:\n" + sb);
} catch (IOException e) {
e.printStackTrace();
}
}
// 字节流追加写入文件
public static void writeFileContent() {
// 第二个参数true:开启追加模式,不覆盖原文件
try (FileOutputStream fos = new FileOutputStream("test.txt", true)) {
String content = "\n新增写入内容:Java IO字节流实战";
fos.write(content.getBytes());
// 强制刷新缓冲区,数据落地
fos.flush();
System.out.println("数据追加写入成功!");
} catch (IOException e) {
e.printStackTrace();
}
}
// 字节流实现媒体文件无损复制(图片/视频/压缩包通用)
public static void copyImageFile() {
try (FileInputStream fis = new FileInputStream("source.jpg");
FileOutputStream fos = new FileOutputStream("target.jpg")) {
byte[] buffer = new byte[1024];
int len;
while ((len = fis.read(buffer)) != -1) {
// 写入有效长度数据,核心避坑点
fos.write(buffer, 0, len);
}
fos.flush();
System.out.println("图片无损复制完成!");
} catch (IOException e) {
e.printStackTrace();
}
}
}
8.4.2 文件字符流(纯文本专属)
FileReader/FileWriter 是纯文本专属节点流,仅用于txt、java、md等文本文件,内置编码解码机制,自动适配文本字符,相比字节流无需手动转换字节数组,中文适配更友好,代码更简洁。
核心局限:无法处理图片、视频等二进制文件,会导致文件损坏、数据丢失。
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
/**
* 文件字符流实战:纯文本专属高效读写
* 核心优势:支持直接读写字符串、自动处理字符编码
* 禁忌:禁止操作二进制媒体文件
*/
public class FileCharStreamDemo {
public static void main(String[] args) {
readTextByChar();
writeTextByChar();
}
// 字符流读取纯文本
public static void readTextByChar() {
try (FileReader fr = new FileReader("text_demo.txt")) {
char[] charBuffer = new char[1024];
int len;
StringBuilder sb = new StringBuilder();
while ((len = fr.read(charBuffer)) != -1) {
sb.append(charBuffer, 0, len);
}
System.out.println("字符流读取文本:\n" + sb);
} catch (IOException e) {
e.printStackTrace();
}
}
// 字符流追加写入文本
public static void writeTextByChar() {
try (FileWriter fw = new FileWriter("text_demo.txt", true)) {
// 直接写入字符串,无需转换,字符流核心优势
fw.write("\nJava字符流专属优势:简化文本读写、适配中文");
fw.flush();
System.out.println("文本内容写入成功!");
} catch (IOException e) {
e.printStackTrace();
}
}
}
高频易错点总结:
-
节点流无缓存,单字节读写性能极差,企业开发禁止直接使用节点流做频繁IO操作;
-
FileWriter/FileReader默认使用项目默认编码,不同环境易乱码,精准编码需用转换流;
-
未指定追加模式时,输出流会清空原文件所有数据,再写入新内容。
8.5 缓冲处理流(企业高性能IO核心)
基础节点流每次读写都会直接操作磁盘,磁盘IO次数多、开销大、性能极低。Java基于装饰器模式提供缓冲流,内置默认8192字节/字符缓冲区,通过内存缓存数据,大幅减少磁盘IO次数,性能提升数十倍,是企业开发IO首选方案。
核心特性:缓冲流属于处理流,必须包装节点流使用,不直接操作数据源;默认缓冲区8KB,支持自定义缓冲区大小。
8.5.1 缓冲字节流
BufferedInputStream/BufferedOutputStream:包装字节节点流,提升所有类型文件的读写效率,适配大文件复制、批量二进制数据传输场景,通用所有文件格式。
8.5.2 缓冲字符流
BufferedReader/BufferedWriter:纯文本高性能处理流,新增两大核心独有方法,是文本处理最优解:
-
readLine():按行读取文本,直接返回字符串,读取完毕返回null;
-
newLine():跨平台换行符,自动适配Windows/Linux/Mac系统换行规则,避免系统兼容问题。
import java.io.*;
/**
* 缓冲流实战:企业高性能IO标准写法
* 核心优势:减少磁盘IO、大幅提升读写效率、支持文本按行操作
*/
public class BufferedStreamDemo {
public static void main(String[] args) {
copyBigFile();
readAndWriteLine();
}
// 缓冲字节流实现大文件高效复制
public static void copyBigFile() {
long startTime = System.currentTimeMillis();
// 缓冲流包装文件节点流,功能增强
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream("video.mp4"));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("video_copy.mp4"))) {
byte[] buffer = new byte[2048];
int len;
while ((len = bis.read(buffer)) != -1) {
bos.write(buffer, 0, len);
}
bos.flush();
long endTime = System.currentTimeMillis();
System.out.println("大文件复制完成,耗时:" + (endTime - startTime) + "ms");
} catch (IOException e) {
e.printStackTrace();
}
}
// 缓冲字符流按行读写文本(日志、配置文件首选)
public static void readAndWriteLine() {
try (BufferedReader br = new BufferedReader(new FileReader("article.txt"));
BufferedWriter bw = new BufferedWriter(new FileWriter("article_copy.txt"))) {
String line;
int lineNum = 1;
// 按行读取,null为读取终止条件
while ((line = br.readLine()) != null) {
bw.write(lineNum + ":" + line);
// 跨平台换行,杜绝系统兼容问题
bw.newLine();
lineNum++;
}
bw.flush();
System.out.println("文本按行复制完成!");
} catch (IOException e) {
e.printStackTrace();
}
}
}
核心避坑点:缓冲流数据写入后,必须执行flush()或close(),否则数据滞留缓冲区,无法落地文件。
8.6 转换流(乱码终极解决方案)
转换流是特殊的处理流,是Java解决文本中文乱码、字节字符流转换的核心方案,核心价值两点:一是实现字节流与字符流的双向转换,二是手动指定读写编码格式,彻底解决不同编码文件交互的乱码问题。
8.6.1 两大转换流核心原理
-
InputStreamReader:字节输入流 → 字符输入流,可指定读取编码(UTF-8/GBK/GB2312);
-
OutputStreamWriter:字符输出流 → 字节输出流,可指定写入编码,统一文件编码格式。
底层本质:转换流=字节流+编码解码器,自定义编码优先级高于系统默认编码,从根源杜绝乱码。
import java.io.*;
/**
* 转换流实战:指定编码读写,彻底解决中文乱码
* 核心场景:GBK文件转UTF-8、跨编码文本交互
*/
public class ConvertStreamDemo {
public static void main(String[] args) {
// GBK编码读取、UTF-8编码写入,实现编码转换
try (BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("gbk_file.txt"), "GBK"));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("utf8_file.txt"), "UTF-8"))) {
String line;
while ((line = br.readLine()) != null) {
bw.write(line);
bw.newLine();
}
bw.flush();
System.out.println("编码转换完成,无中文乱码!");
} catch (IOException e) {
e.printStackTrace();
}
}
}
面试核心考点:
-
普通FileReader/FileWriter无法指定编码,仅能使用默认编码,极易乱码;
-
转换流是唯一可以自定义编码格式的基础文本流,是乱码问题的终极解决方案。
8.7 企业高频特殊功能流(拓展核心)
8.7.1 打印流(PrintWriter)
PrintWriter 是高效便捷字符打印流,是企业日志输出、文件写入的常用工具,具备自动换行、自动刷新、支持任意数据类型输出三大核心优势,无IO异常强制捕获,代码极简。
import java.io.PrintWriter;
/**
* 打印流实战:极简文本写入、日志输出
* 优势:无需手动类型转换、自动换行、自动刷新
*/
public class PrintWriterDemo {
public static void main(String[] args) {
try (PrintWriter pw = new PrintWriter("print_demo.txt")) {
// 支持字符串、数字、布尔值等所有类型直接输出
pw.println("Java IO打印流");
pw.println(2026);
pw.println(3.14159);
pw.println(true);
pw.flush();
System.out.println("打印流数据写入完成!");
} catch (Exception e) {
e.printStackTrace();
}
}
}
8.7.2 数据流(基本类型精准读写)
DataInputStream/DataOutputStream 专门用于Java基本数据类型、字符串的精准读写,可直接写入int、double、boolean等类型,无需手动类型转换。
核心强制规范:数据读取顺序必须严格匹配写入顺序,否则数据错乱、报错。
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* 数据流实战:基本数据类型精准持久化读写
* 核心规范:读写顺序严格一致
*/
public class DataStreamDemo {
public static void main(String[] args) {
writeData();
readData();
}
// 写入基础数据
public static void writeData() {
try (DataOutputStream dos = new DataOutputStream(new FileOutputStream("data_stream"))) {
dos.writeInt(2026);
dos.writeDouble(66.88);
dos.writeBoolean(true);
dos.writeUTF("Java数据流实战");
dos.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
// 严格按写入顺序读取数据
public static void readData() {
try (DataInputStream dis = new DataInputStream(new FileInputStream("data_stream"))) {
System.out.println("整数年份:" + dis.readInt());
System.out.println("数值数据:" + dis.readDouble());
System.out.println("布尔状态:" + dis.readBoolean());
System.out.println("字符串内容:" + dis.readUTF());
} catch (IOException e) {
e.printStackTrace();
}
}
}
8.7.3 对象流(序列化与反序列化核心)
对象流 ObjectInputStream/ObjectOutputStream 是实现Java对象持久化、网络对象传输的核心流,可将内存中的Java对象直接写入文件,也可从文件读取恢复为内存对象。
核心底层概念:
-
序列化:内存Java对象 → 二进制字节序列(持久化存储/网络传输);
-
反序列化:二进制字节序列 → 还原为内存Java对象;
强制规范:被序列化的实体类必须实现Serializable空标记接口,否则抛出序列化异常。
核心面试考点:serialVersionUID序列化版本号,保证实体类版本升级后,新旧数据兼容,避免反序列化失败。
import java.io.*;
// 实体类实现序列化标记接口
class User implements Serializable {
// 固定序列化版本号,保证版本兼容(必写规范)
private static final long serialVersionUID = 1L;
private Integer id;
private String username;
private String email;
public User(Integer id, String username, String email) {
this.id = id;
this.username = username;
this.email = email;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", email='" + email + '\'' +
'}';
}
}
/**
* 对象流实战:对象序列化持久化与反序列化恢复
* 核心坑点:必须实现Serializable、版本号一致、读写顺序匹配
*/
public class ObjectStreamDemo {
public static void main(String[] args) {
serializeObject();
deserializeObject();
}
// 对象序列化:内存对象写入文件持久化
public static void serializeObject() {
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("user_object"))) {
User user = new User(1001, "Java学习者", "java@163.com");
oos.writeObject(user);
oos.flush();
System.out.println("对象序列化成功!");
} catch (IOException e) {
e.printStackTrace();
}
}
// 对象反序列化:文件字节恢复为内存对象
public static void deserializeObject() {
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("user_object"))) {
User user = (User) ois.readObject();
System.out.println("反序列化读取对象:\n" + user);
} catch (Exception e) {
e.printStackTrace();
}
}
}
序列化高频避坑点:
-
transient修饰的属性无法被序列化,会默认赋值为初始值;
-
反序列化无需执行构造方法,直接通过字节数据还原对象;
-
版本号不一致,直接抛出
InvalidClassException版本异常。
8.8 File文件操作类(文件属性管理)
java.io.File 是专门用于文件/文件夹属性操作的工具类,不负责文件内容读写,仅处理文件创建、删除、路径获取、遍历、权限判断等属性操作,常与IO流配合完成完整文件处理流程。
核心职责边界:File管文件属性、IO流管文件内容读写。
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
/**
* File类实战:文件与文件夹全套属性操作
* 职责:仅操作文件属性,不读写文件内容
*/
public class FileDemo {
public static void main(String[] args) {
createFile();
createDir();
getFileInfo();
listDirFile();
}
// 创建空文件
public static void createFile() {
File file = new File("new_file.txt");
try {
if (!file.exists()) {
boolean result = file.createNewFile();
System.out.println("文件创建结果:" + result);
}
} catch (IOException e) {
e.printStackTrace();
}
}
// 创建多级文件夹
public static void createDir() {
File dir = new File("file_demo/java/io");
if (!dir.exists()) {
// mkdirs:创建多级目录;mkdir:仅创建单级目录
boolean result = dir.mkdirs();
System.out.println("多级文件夹创建结果:" + result);
}
}
// 获取文件详细属性
public static void getFileInfo() {
File file = new File("new_file.txt");
System.out.println("文件绝对路径:" + file.getAbsolutePath());
System.out.println("文件大小:" + file.length() + " 字节");
System.out.println("是否为文件:" + file.isFile());
System.out.println("是否为文件夹:" + file.isDirectory());
System.out.println("文件是否存在:" + file.exists());
}
// 遍历文件夹下所有文件
public static void listDirFile() {
File dir = new File("file_demo");
File[] files = dir.listFiles();
if (files != null) {
System.out.println("文件夹内文件列表:" + Arrays.toString(files));
}
}
}
File类高频坑点:
-
listFiles()返回null,需做空判断,避免空指针异常; -
mkdir()仅创建单级目录,多级目录必须使用mkdirs();
-
File对象创建不代表文件存在,仅为路径映射,需手动createNewFile创建真实文件。
8.9 装饰器模式在IO流中的底层应用
Java IO流体系能够灵活拓展、功能解耦,核心底层依托装饰器设计模式,是面试高频原理考点。
8.9.1 装饰器模式核心思想
不修改原有类源码,通过包装原有对象,动态增强原有对象的功能,实现功能解耦、灵活拓展。
8.9.2 IO流中的落地实现
-
被装饰对象(基础角色):节点流(FileInputStream、FileReader),具备基础读写功能,功能单一;
-
装饰器对象(增强角色):处理流(缓冲流、转换流、打印流),包装节点流,动态新增缓存、编码转换、按行读取等功能;
-
核心案例:
new BufferedInputStream(new FileInputStream()),用缓冲流装饰文件字节流,在基础读写功能上,新增缓存提速能力。
设计优势:无需定义大量冗余子类,通过层层包装即可灵活组合功能,完美适配各类IO场景。
8.10 Apache Commons-IO企业级工具类
Java原生IO代码冗余、模板代码多、需手动处理异常和流关闭、坑点较多。Apache开源的commons-io工具类封装了全套极简IO操作,一行代码实现文件读写、复制、删除,是目前企业开发主流选择。
8.10.1 核心优势
-
自动关闭流,杜绝资源泄露;
-
极简代码,无需手写循环读写、刷新关闭;
-
自带编码适配、文件过滤、大文件处理机制;
-
规避原生IO所有高频坑点,代码健壮性极强。
8.10.2 核心工具类与实战
-
FileUtils:文件/目录批量操作(读写、复制、删除、遍历);
-
IOUtils:流通用操作(流转换、拷贝、关闭)。
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import java.io.File;
import java.io.FileInputStream;
import java.nio.charset.StandardCharsets;
/**
* Commons-IO工具类企业实战
* 核心:极简代码、零模板、自动资源释放
*/
public class CommonsIODemo {
public static void main(String[] args) throws Exception {
// 1. 一行代码读取整个文本文件
String fileContent = FileUtils.readFileToString(new File("test.txt"), StandardCharsets.UTF_8);
System.out.println("工具类读取文件:\n" + fileContent);
// 2. 一行代码写入文本内容
FileUtils.writeStringToFile(new File("commons_write.txt"), "Commons-IO极简IO开发", StandardCharsets.UTF_8);
// 3. 整文件夹批量复制
FileUtils.copyDirectory(new File("source_dir"), new File("target_dir"));
// 4. 流快速转换为字符串
String streamStr = IOUtils.toString(new FileInputStream("test.txt"), StandardCharsets.UTF_8);
System.out.println("流转换字符串:" + streamStr);
}
}
8.11 本章高频坑点全汇总(开发/面试必背)
1. 流向混淆坑点
-
IO读写方向仅以程序内存为标准,外部设备不参与方向判断;
-
输入流只能读、输出流只能写,不可混用。
2. 字节流与字符流选型坑点
-
媒体文件、二进制文件必须用字节流,字符流操作会文件损坏;
-
纯文本优先字符流,代码更简洁、适配中文,性能更优。
3. 缓冲区坑点
-
字符流、缓冲流必须flush/close,否则数据滞留内存不落地;
-
批量读写必须使用有效长度len,禁止直接写入完整缓冲区,避免空数据冗余。
4. 乱码坑点
-
原生FileReader/FileWriter无法指定编码,跨环境极易乱码;
-
精准编码读写必须使用转换流InputStreamReader/OutputStreamWriter。
5. 序列化坑点
-
序列化实体类必须实现Serializable接口,否则报错;
-
必须手动定义serialVersionUID,避免类结构变更导致反序列化失败;
-
transient属性无法序列化,读写顺序必须严格一致。
6. 资源泄露坑点
-
所有IO流必须关闭,JDK7+强制使用try-with-resource语法;
-
禁止手动写finally关闭流,代码冗余且易出错。
7. 文件覆盖坑点
- 输出流默认清空原文件内容再写入,追加写入必须手动开启true追加参数。
8.12 本章核心知识点终极总结
-
IO流是程序与外部数据交互的核心,分为输入(读)、输出(写),流向唯一参照标准为程序内存,是所有文件操作、网络通信的基础;
-
字节流通用所有文件,字符流专属纯文本文件;节点流为基础底层流,处理流基于装饰器模式动态增强功能,企业开发优先使用缓冲处理流;
-
四大顶层抽象父类统一所有IO流规范,字节流无缓冲区、字符流自带缓冲区,缓冲区数据必须刷新落地;
-
转换流是解决中文乱码、编码转换的核心,可自定义读写编码,适配跨编码文件交互场景;
-
对象流依托序列化机制实现对象持久化与网络传输,实体类必须实现序列化接口,版本号兼容是核心规范;
-
File类仅管理文件属性,IO流负责文件内容读写,二者配合实现完整文件处理流程;
-
企业级开发规范:优先try-with-resource自动关流、优先缓冲流提升性能、优先commons-io工具类简化代码,严格区分流的选型场景,规避所有IO性能与异常坑点。
更多推荐
所有评论(0)