Java学习25
·
上午 3h:转换流(解决中文乱码终极方案)
1. 编码问题铺垫(0.5h)
1.1 乱码是怎么来的?
- 写的时候用 UTF-8
- 读的时候用 GBK👉 编码不一致 = 乱码
1.2 常见编码
- UTF-8:国际通用,中文占 3 字节
- GBK:Windows 系统默认,中文占 2 字节
- ASCII:英文
1.3 普通字符流的缺点
FileReader / FileWriter 只能用系统默认编码,不能手动指定。👉 遇到非系统编码文件 必乱码。
2. 转换流核心作用(0.4h)
一句话记住
转换流 = 字节流 + 编码表 → 字符流
两大作用
- 把字节流 → 字符流
- 手动指定编码(UTF-8/GBK)
- 彻底解决中文乱码
两个类
- InputStreamReader:字节输入流 → 字符输入流(读)
- OutputStreamWriter:字节输出流 → 字符输出流(写)
3. 转换输入流:InputStreamReader(1.05h)
作用
以指定编码读取文件
构造方法
java
运行
InputStreamReader isr = new InputStreamReader(
new FileInputStream("文件路径"),
"GBK" // 可以写 UTF-8
);
完整代码(指定 GBK 读取不乱码)
java
运行
import java.io.*;
public class ISRDemo {
public static void main(String[] args) throws IOException {
// 以 GBK 编码读取文件
InputStreamReader isr = new InputStreamReader(
new FileInputStream("D:\\JavaDay17\\gbk.txt"),
"GBK"
);
char[] chs = new char[1024];
int len;
while ((len = isr.read(chs)) != -1) {
System.out.print(new String(chs, 0, len));
}
isr.close();
}
}
解释
- 无论文件是什么编码,只要指定对,就不乱码
- 这是解决乱码的标准方案
4. 转换输出流:OutputStreamWriter(1.05h)
作用
以指定编码写文件
构造方法
java
运行
OutputStreamWriter osw = new OutputStreamWriter(
new FileOutputStream("路径"),
"UTF-8"
);
完整代码(UTF-8 写入)
java
运行
import java.io.*;
public class OSWDemo {
public static void main(String[] args) throws IOException {
// 以 UTF-8 编码写入
OutputStreamWriter osw = new OutputStreamWriter(
new FileOutputStream("D:\\JavaDay17\\utf8.txt"),
"UTF-8"
);
osw.write("我是UTF-8编码的中文");
osw.close();
}
}
5. 转换流使用场景总结
- 读取老旧 GBK 文件
- 跨平台文本传输
- 必须指定编码的场景
- 解决所有中文乱码
下午 2.5h:对象序列化流(存对象、读对象)
1. 序列化概念(0.4h)
序列化
对象 → 字节数组 → 保存到文件
反序列化
文件字节 → 还原成对象
应用
- 保存用户登录状态
- 本地缓存对象
- 网络传输对象
2. 序列化流:ObjectOutputStream(1.05h)
必须满足
实体类必须实现 Serializable 接口
步骤
- 写一个类(如 Student)
- 实现
Serializable - 使用
writeObject()写入
完整代码
① Student.java
java
运行
import java.io.Serializable;
// 必须加这个接口
public class Student implements Serializable {
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student{" + "name=" + name + ", age=" + age + "}";
}
}
② 序列化写入文件
java
运行
import java.io.*;
public class WriteObject {
public static void main(String[] args) throws IOException {
ObjectOutputStream oos = new ObjectOutputStream(
new FileOutputStream("D:\\JavaDay17\\student.txt")
);
// 写入对象
Student stu = new Student("张三", 20);
oos.writeObject(stu);
oos.close();
}
}
3. 反序列化流:ObjectInputStream(1.05h)
方法
readObject()
完整代码
java
运行
import java.io.*;
public class ReadObject {
public static void main(String[] args) throws Exception {
ObjectInputStream ois = new ObjectInputStream(
new FileInputStream("D:\\JavaDay17\\student.txt")
);
// 读取并还原对象
Student stu = (Student) ois.readObject();
System.out.println(stu);
ois.close();
}
}
重要关键字:transient
java
运行
transient private int age;
被 transient 修饰的变量 → 不参与序列化 → 读到是默认值 0 /null
晚上 1.5h:IO 综合强化练习
1. 转换流读写 UTF-8、GBK(必做)
java
运行
// 读GBK
InputStreamReader isr = new InputStreamReader(new FileInputStream("a.txt"),"GBK");
// 写UTF-8
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("b.txt"),"UTF-8");
2. 序列化与反序列化(必做)
上面完整代码。
3. 文件夹复制(递归 + 字节流)
这是大综合案例,包含:
- 文件判断
- 文件夹创建
- 递归
- 字节流复制
完整代码
java
运行
import java.io.*;
public class CopyFolder {
public static void main(String[] args) throws IOException {
File src = new File("D:\\JavaDay17\\源文件夹");
File dest = new File("D:\\JavaDay17\\目标文件夹");
copyDir(src, dest);
}
// 复制文件夹
public static void copyDir(File src, File dest) throws IOException {
if (src.isFile()) {
// 是文件 → 复制
FileInputStream fis = new FileInputStream(src);
FileOutputStream fos = new FileOutputStream(new File(dest, src.getName()));
byte[] buf = new byte[8192];
int len;
while ((len = fis.read(buf)) != -1) {
fos.write(buf, 0, len);
}
fos.close();
fis.close();
return;
}
// 创建目标文件夹
File newDir = new File(dest, src.getName());
newDir.mkdirs();
// 遍历子文件
File[] files = src.listFiles();
for (File f : files) {
copyDir(f, newDir);
}
}
}
一、先告诉你:这段代码是干嘛的?
把一个文件夹(包括里面所有子文件夹、所有文件)完整复制到另一个地方,一模一样。
例子:
- 源:
D:\JavaDay17\源文件夹 - 目标:
D:\JavaDay17\目标文件夹运行后 → 源文件夹整个被复制到目标文件夹里
二、整体结构
java
运行
public class CopyFolder {
public static void main(String[] args) throws IOException {
// 1. 定义源、目标
// 2. 调用方法复制
}
public static void copyDir(File src, File dest) throws IOException {
// 核心递归方法
}
}
三、逐行详细讲解
1️⃣ 主方法 main
java
运行
public static void main(String[] args) throws IOException {
File src = new File("D:\\JavaDay17\\源文件夹");
File dest = new File("D:\\JavaDay17\\目标文件夹");
copyDir(src, dest);
}
知识点
File类:不代表文件内容,代表路径 / 文件夹 / 文件的抽象throws IOException:IO 操作可能出错(文件找不到、权限不足),声明抛出- 作用:
- 告诉程序从哪复制
- 告诉程序复制到哪
- 调用
copyDir开始干活
2️⃣ 核心方法:copyDir(递归复制)
重点:递归!递归!递归!
自己调用自己,直到把所有文件都复制完。
第一步:判断是不是文件
java
运行
if (src.isFile()) {
// 是文件 → 复制
}
知识点
isFile():判断当前路径 是不是一个文件- 如果是文件 → 进入复制逻辑
- 如果是文件夹 → 跳过,走后面逻辑
第二步:如果是文件,开始复制
java
运行
FileInputStream fis = new FileInputStream(src);
FileOutputStream fos = new FileOutputStream(new File(dest, src.getName()));
讲解
FileInputStream:字节输入流 → 读文件FileOutputStream:字节输出流 → 写文件
java
运行
new File(dest, src.getName())
意思:在目标文件夹下,创建一个和源文件同名的文件
例子:源文件:a.jpg目标路径:目标文件夹/a.jpg
第三步:使用字节数组高速复制
java
运行
byte[] buf = new byte[8192];
int len;
while ((len = fis.read(buf)) != -1) {
fos.write(buf, 0, len);
}
超级重要知识点
-
byte[] buf = new byte[8192]缓冲区,一次读 8KB 数据,速度极快 -
fis.read(buf)一次读一堆数据到数组里返回值:读到的有效字节数 -
len == -1:文件读完了 -
fos.write(buf,0,len)把读到的数据写入目标文件
第四步:关流
java
运行
fos.close();
fis.close();
- 流使用完必须关闭
- 释放资源
- 防止文件被占用
第五步:如果是文件夹,创建文件夹
java
运行
File newDir = new File(dest, src.getName());
newDir.mkdirs();
讲解
- 在目标位置,创建一个和源文件夹同名的文件夹
mkdirs():创建多级文件夹(最常用)
第六步:遍历文件夹里的所有内容
java
运行
File[] files = src.listFiles();
for (File f : files) {
copyDir(f, newDir);
}
核心:递归!
listFiles():获取文件夹里所有子文件 / 子文件夹- 遍历每一个
- 再次调用 copyDir自己调用自己!
四、整套代码运行顺序(超级重要)
我给你走一遍流程,你马上懂递归!
运行顺序
- main 方法启动
- 进入
copyDir(源文件夹, 目标文件夹) - 判断:源文件夹 → 是文件夹
- 创建:
目标文件夹\源文件夹 - 获取里面所有子文件
- 遍历每一个:
- 如果是文件 → 复制
- 如果是文件夹 → 再次进入 copyDir重复 3~6 步骤!
一句话总结递归逻辑
是文件就复制
是文件夹就创建,然后进去继续遍历
文件 = 有内容 → 必须用流读写
文件夹 = 只是个空目录 → 只需要创建,不需要读写
今日核心复盘(必背)
- 转换流 = 字节流 + 编码 → 解决乱码
- InputStreamReader 读指定编码
- OutputStreamWriter 写指定编码
- 序列化:对象 → 文件
- 反序列化:文件 → 对象
- 必须实现 Serializable
- transient 不序列化
- 文件夹复制 = 递归 + 字节流
更多推荐


所有评论(0)