一、字节流
1. FileInputStream 读取全部字节
字节流可处理所有类型文件(文本、图片、视频等),核心是通过字节数组提升读取效率。
方式 1:自定义字节数组读取(推荐)
原理:创建与文件大小一致的字节数组,一次性读取全部数据,避免乱码问题。
public class FileInputStreamTest1 {
public static void main(String[] args) throws Exception {
// 1. 创建字节输入流,绑定目标文件
FileInputStream is = new FileInputStream("day10/src/yy02.txt");
// 2. 获取文件大小
File f = new File("day10/src/yy02.txt");
long size = f.length();
// 3. 创建和文件大小一致的字节数组
byte[] buffer = new byte[(int) size];
// 4. 读取全部字节
int len = is.read(buffer);
// 5. 转字符串输出
System.out.println(new String(buffer));
// 6. 关闭流
is.close();
}
}
2. FileOutputStream 写入字节
作用:以内存为基准,将内存中的数据以字节形式写入文件,支持覆盖 / 追加两种模式。
核心方法与代码示例
public class FileOutputStreamTest {
public static void main(String[] args) throws Exception {
// 1. 创建字节输出流,第二个参数true表示追加写入,默认false为覆盖
FileOutputStream os = new FileOutputStream("day10/src/yy03.txt", true);
// 2. 写入单个字节
os.write('a');
os.write(97); // 写入ASCII码对应的字符
// 3. 写入整个字节数组
byte[] bytes = "我爱Javaabc".getBytes();
os.write(bytes);
// 4. 写入字节数组的一部分(从下标0开始,写入5个字节)
os.write(bytes, 0, 5);
// 5. 关闭流
os.close();
}
}
3. 字节流复制文件(通用方案)
原理:边读边写,通过字节数组作为缓冲区,实现所有文件的高效复制。
public class CopyDemo {
public static void main(String[] args) throws Exception {
// 1. 源文件输入流(读取)
InputStream is = new FileInputStream("D:/resource/meinv.png");
// 2. 目标文件输出流(写入)
OutputStream os = new FileOutputStream("E:/data/meinv.png");
// 3. 创建缓冲区(1024的整数倍,提升效率)
byte[] buffer = new byte[1024];
int len;
// 4. 循环读写:读多少写多少
while ((len = is.read(buffer)) != -1) {
os.write(buffer, 0, len);
}
// 5. 关闭流(先关输出流,再关输入流)
os.close();
is.close();
System.out.println("复制完成!");
}
}
二、IO 流资源释放(核心避坑)
1. 问题根源
流是操作系统资源,程序异常终止时,close() 无法执行,会导致资源泄漏,后续操作会报 Stream Closed 异常。
2. JDK7 之前:try-catch-finally 方案
finally 块保证代码一定会执行,确保流被关闭。
public class CopyDemo1 {
public static void main(String[] args) {
InputStream is = null;
OutputStream os = null;
try {
// 初始化流
is = new FileInputStream("D:/resource/meinv.png");
os = new FileOutputStream("E:/data/meinv.png");
byte[] buffer = new byte[1024];
int len;
while ((len = is.read(buffer)) != -1) {
os.write(buffer, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
// finally中判空关闭流,避免空指针
try {
if (os != null) os.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if (is != null) is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
3. JDK7+:try-with-resources 方案(推荐)
流对象实现 AutoCloseable 接口,代码块执行完毕后自动关闭流,无需手动写 finally。
public class CopyDemo2 {
public static void main(String[] args) {
// try()中声明流对象,自动管理关闭
try (
InputStream is = new FileInputStream("D:/resource/meinv.png");
OutputStream os = new FileOutputStream("E:/data/meinv.png")
) {
byte[] buffer = new byte[1024];
int len;
while ((len = is.read(buffer)) != -1) {
os.write(buffer, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
三、字符流(FileReader & FileWriter)
1. 字符流体系与适用场景
- 顶层父类:
Reader(输入)、Writer(输出) - 常用子类:
FileReader(读取文本)、FileWriter(写入文本) - 适用场景:仅处理纯文本文件,自动适配字符编码,避免中文乱码。
2. FileReader 读取文本文件
核心构造方法
| 构造方法 | 说明 |
|---|---|
FileReader(File file) | 通过 File 对象创建字符输入流 |
FileReader(String pathname) | 通过文件路径创建字符输入流 |
常用读取方式
public class FileReaderTest {
public static void main(String[] args) throws Exception {
FileReader fr = new FileReader("day10/src/yy02.txt");
// 方式1:单个字符读取
/*
int ch;
while ((ch = fr.read()) != -1) {
System.out.print((char) ch);
}
*/
// 方式2:字符数组读取(推荐,效率高)
char[] buffer = new char[1024];
int len;
while ((len = fr.read(buffer)) != -1) {
System.out.print(new String(buffer, 0, len));
}
fr.close();
}
}
3. FileWriter 写入文本文件
核心构造方法
| 构造方法 | 说明 |
|---|---|
FileWriter(File file) | 创建覆盖模式的字符输出流 |
FileWriter(String pathname, boolean append) | append=true 开启追加模式 |
常用写入方法与示例
public class FileWriterTest {
public static void main(String[] args) throws Exception {
// 追加模式写入
FileWriter fw = new FileWriter("day10/src/yy03.txt", true);
// 1. 写入单个字符
fw.write('中');
fw.write(97);
// 2. 写入字符串(字符流特有便捷方法)
fw.write("Java 字符流学习");
// 3. 写入字符数组
char[] chars = {'a', 'b', 'c', '我', '爱', '编', '程'};
fw.write(chars);
// 4. 写入字符串的一部分
fw.write("abcdef", 1, 3);
// 手动刷新缓冲区(数据落地到文件)
fw.flush();
// 关闭流(会自动刷新缓冲区)
fw.close();
}
}
注意:字符流自带缓冲区,数据不会直接写入磁盘,必须调用 flush() 或 close() 才能让数据落地。
4. 字符流复制纯文本文件
public class CharCopyDemo {
public static void main(String[] args) throws Exception {
FileReader fr = new FileReader("day10/src/yy03.txt");
FileWriter fw = new FileWriter("day10/src/copy_yy03.txt");
char[] buffer = new char[1024];
int len;
while ((len = fr.read(buffer)) != -1) {
fw.write(buffer, 0, len);
}
fw.close();
fr.close();
System.out.println("文本复制完成!");
}
}
四、字节流 vs 字符流 核心对比
| 对比维度 | 字节流 | 字符流 |
|---|---|---|
| 顶层父类 | InputStream / OutputStream | Reader / Writer |
| 处理单位 | 字节(byte) | 字符(char) |
| 适用场景 | 所有文件(文本、图片、视频、压缩包) | 仅纯文本文件 |
| 乱码问题 | 可能出现,需手动处理编码 | 自动适配编码,中文不乱码 |
| 缓冲区 | 无,读写直接生效 | 有,需 flush()/close() 数据才落地 |
| 开发首选场景 | 文件复制、非文本文件读写 | 纯文本文件读写 |

242

被折叠的 条评论
为什么被折叠?



