本阶段涵盖:File 文件操作与 IO 流入门、IO 缓冲流与字符流、转换流与对象序列化 细分文档:
按日细分/20260806-笔记.md、按日细分/20260807-笔记.md、按日细分/20260808-笔记.md(转换流/序列化部分) 学生需要重点理解、背诵、掌握的理论核心知识点。
File 是文件和目录路径名的抽象表示——不一定是真实存在的文件,只是一个路径名。File 只描述路径、不做真正的读写(真正读写用 IO 流)。
new File(String pathname)
new File(String parent, String child)
new File(File parent, String child)
\;Linux/UNIX /| 分类 | 方法 |
|---|---|
| 创建 | createNewFile()(抛 IOException)/ mkdir() / mkdirs()(多级) |
| 删除 | delete() |
| 判断 | isFile() / isDirectory() / exists() |
| 获取 | getAbsolutePath() / getPath() / getName() / listFiles()(File[] 数组) |
| 维度 | 类别 |
|---|---|
| 按数据流向 | 输入流(读)、输出流(写) |
| 按数据类型 | 字节流(byte)、字符流(char) |
OutputStream / InputStream;子类名以父类名作后缀(FileOutputStream、FileInputStream)使用三步:①创建流对象 ②调用写方法 ③关闭流
(File) / (String) / (File, append) / (String, append)——append=true 追加否则覆盖write(int b) / write(byte[] b) / write(byte[] b, off, len)getBytes()\n;Windows \r\n;macOS \r使用三步:①创建流对象 ②调用读方法 ③关闭流
read() / read(byte[] b) / read(byte[] b, off, len)read() 返回 -1 表示 EOF;read(byte[]) 返回本次有效长度经典循环读写法(必背):
FileInputStream fis = new FileInputStream("E:/我的文件.txt");
byte[] bytes = new byte[1024];
int length;
while ((length = fis.read(bytes)) != -1) {
System.out.println(new String(bytes, 0, length, Charset.forName("UTF-8")));
}
fis.close();
用 try-catch-finally 关闭资源,finally 保证 close()。
byte[] bytes = new byte[4096]; // 缓冲区思想:一次读/写一批
int length;
while ((length = fis.read(bytes)) != -1) {
fos.write(bytes, 0, length); // 只写本次有效字节
}
fos.close(); // 先关输出流,再关输入流
fis.close();
缓冲区越大、磁盘 I/O 越少、效率越高。耗时统计用
System.currentTimeMillis()。
接口定义复制规范,多种实现(普通字节流 vs 缓冲流),调用方只依赖接口——多态可随时替换。
BufferedOutputStream / BufferedInputStream:包装流/装饰流,给底层字节流加缓冲new BufferedOutputStream(fos)包装流程:先建文件流 → 缓冲流包装 → 操作缓冲流 → 关闭(先关缓冲再关底层)
缓冲流默认缓冲区满了才落盘;flush() 手动强制刷新。
close() 之前会自动 flush 一次;flush 用于"不关闭流但需及时看到数据"。
字符流 = 字节流 + 字符集编码表——解决字节流操作中文不方便的问题。
字符集: ASCII / GB-2312 / GBK / Unicode(UTF-8)
字符串.getBytes()(字符串 → 字节)new String(byte[])(字节 → 字符串)字符流体系:
Reader(输入字符流抽象类)→ FileReader
Writer(输出字符流抽象类)→ FileWriter
字符流核心优势(必背):
write(String) 写字符串,无需 getBytes()——操作中文方便flush()read() 返回 -1 表示 EOF;read(char[]) 返回有效字符数| 流 | 特有方法 | 说明 |
|---|---|---|
BufferedWriter |
newLine() |
写跨平台行分隔符 |
BufferedReader |
readLine() |
读一行(不含终止符),EOF 返回 null |
经典逐行读(必背):
BufferedReader br = new BufferedReader(new FileReader("D:/scores.txt"));
String line;
while ((line = br.readLine()) != null) { ... }
br.close();
基础流:
字节流:InputStream → FileInputStream / OutputStream → FileOutputStream
字符流:Reader → FileReader / Writer → FileWriter
处理流(扩展流)- 缓冲流:
缓冲字节流:BufferedInputStream / BufferedOutputStream
缓冲字符流:BufferedReader / BufferedWriter
选型口诀:不确定用字节流;纯文本用字符流;要效率加缓冲流。
乱码根源:同一字节在不同字符集含义不同——用 A 编码、用 B 解码就乱码。
模型:字符 --编码--> 字节 --解码--> 字符
| 桥梁 | 父类 | 方向 | 动作 |
|---|---|---|---|
InputStreamReader |
Reader | 字节 → 字符 | 解码 |
OutputStreamWriter |
Writer | 字符 → 字节 | 编码 |
new InputStreamReader(new FileInputStream("D:/abc.txt"), "UTF-8"); // 读端指定源编码
new OutputStreamWriter(new FileOutputStream("D:/hello.txt"), "GBK"); // 写端指定目标编码
对象持久化:把内存对象保存到磁盘 / 网络传输——本质是把对象变成字节序列(含类型、数据、属性)。
序列化:对象 --ObjectOutputStream.writeObject()--> 字节序列 --> 文件
反序列化:文件 --ObjectInputStream.readObject()--> 字节序列 --> 内存重构对象
Serializable 接口(标记接口:无方法无属性,仅作"可序列化"标识)readObject() 返回 Object,需强转;抛 ClassNotFoundExceptionInvalidClassExceptionprivate static final long serialVersionUID = 42L;transient 修饰的成员不参与序列化,反序列化为默认值(引用 null)。
readResolve()基础流:字节流(FileInputStream/FileOutputStream)、字符流(FileReader/FileWriter)
处理流:缓冲流(BufferedInputStream/OutputStream、BufferedReader/Writer)
转换流(InputStreamReader 解码 / OutputStreamWriter 编码)
对象流(ObjectOutputStream 序列化 / ObjectInputStream 反序列化)