Java IO 流文件复制全解:字符缓冲流 vs 字节缓冲流
一、需求场景解析
本次竞赛题的核心是两种文件复制场景:
文本文件复制:专门处理 .txt/.java 等文本文件,推荐使用字符缓冲流
任意文件复制:支持图片、视频、压缩包等所有类型文件,推荐使用字节缓冲流
二、文本文件复制:字符缓冲流(BufferedReader/BufferedWriter)
字符缓冲流是处理文本文件的首选,自带缓冲区,读写效率极高,还支持按行读取的便捷操作
核心代码:
import java.io.*;
public class TextFileCopy {
public static void main(String[] args) {
// 源文件路径
String srcPath = "src/original.txt";
// 目标文件路径
String destPath = "src/copy.txt";
// try-with-resources 自动关闭流,避免资源泄漏
try (BufferedReader br = new BufferedReader(new FileReader(srcPath));
BufferedWriter bw = new BufferedWriter(new FileWriter(destPath))) {
String line;
// 按行读取文本文件
while ((line = br.readLine()) != null) {
bw.write(line);
// 写入换行符(不同系统换行符不同,也可使用 bw.newLine())
bw.newLine();
}
System.out.println("文本文件复制完成!");
} catch (IOException e) {
e.printStackTrace();
}
}
}
关键知识点 BufferedReader.readLine():
按行读取文本,自动处理换行符,适合文本文件场景 BufferedWriter.newLine():
写入系统默认的换行符,跨平台兼容性更好 适用场景:
纯文本文件(.txt、.java、.html 等),不适合处理图片、视频等二进制文件
三、任意文件复制:字节缓冲流(BufferedInputStream/BufferedOutputStream)
字节流是 “万能流”,可以处理所有类型的文件,加上缓冲流后效率大幅提升,是文件复制的通用方案。
核心代码实现
import java.io.*;
public class AnyFileCopy {
public static void main(String[] args) {
// 源文件路径(支持图片、视频、压缩包等)
String srcPath = "src/original.jpg";
// 目标文件路径
String destPath = "src/copy.jpg";
// 定义缓冲区大小(常用 8KB 或 4KB)
byte[] buffer = new byte[8192];
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcPath));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destPath))) {
int len;
// 循环读取文件数据到缓冲区
while ((len = bis.read(buffer)) != -1) {
// 将缓冲区的数据写入目标文件
bos.write(buffer, 0, len);
}
System.out.println("文件复制完成!");
} catch (IOException e) {
e.printStackTrace();
}
}
}
关键知识点
- 字节流的本质:直接操作文件的二进制数据,不关心文件格式,因此支持所有类型文件
- 缓冲区优化:
byte[] buffer减少了磁盘 IO 次数,大幅提升复制效率 bis.read(buffer):返回实际读取到的字节数,len == -1表示文件读取完毕bos.write(buffer, 0, len):写入时只写实际读取到的字节,避免缓冲区残留数据导致文件损坏
四、两种方案对比
| 对比项 | 字符缓冲流(BufferedReader/BufferedWriter) | 字节缓冲流(BufferedInputStream/BufferedOutputStream) |
|---|---|---|
| 适用文件类型 | 仅文本文件 | 所有类型文件(文本、图片、视频、压缩包等) |
| 处理单位 | 字符(char) | 字节(byte) |
| 核心优势 | 按行读取文本,操作便捷,效率高 | 通用性强,二进制文件无乱码问题 |
| 典型场景 | 复制日志、配置文件、代码文件 | 复制图片、视频、安装包等任意文件 |
| 乱码风险 | 处理非文本文件会乱码 | 无乱码风险 |
五、竞赛题常见考点与优化技巧
1. 为什么要用缓冲流?
直接使用FileInputStream/FileOutputStream每次读写都要访问磁盘,效率极低;缓冲流会先将数据读到内存缓冲区,批量读写,减少磁盘 IO 次数,性能提升非常明显。
2. 缓冲区大小怎么选?
常用大小为 4KB(4096)或 8KB(8192),和磁盘扇区大小匹配,能最大化读写效率。过大的缓冲区会占用过多内存,过小则起不到优化效果。
3. try-with-resources 的重要性
必须使用 try-with-resources 语法自动关闭流,避免手动close()时出现异常导致资源泄漏,这也是 Java IO 编程的规范写法。
4. 文本文件复制的换行问题
使用readLine()读取时,会自动去掉换行符,因此写入时必须调用newLine()补充换行符,否则复制后的文件会变成一行。
六、完整工具类封装
可以把两种复制方式封装成通用工具类,直接调用即可:
import java.io.*;
public class FileCopyUtils {
// 文本文件复制(字符缓冲流)
public static void copyTextFile(String srcPath, String destPath) throws IOException {
try (BufferedReader br = new BufferedReader(new FileReader(srcPath));
BufferedWriter bw = new BufferedWriter(new FileWriter(destPath))) {
String line;
while ((line = br.readLine()) != null) {
bw.write(line);
bw.newLine();
}
}
}
// 任意文件复制(字节缓冲流)
public static void copyAnyFile(String srcPath, String destPath) throws IOException {
byte[] buffer = new byte[8192];
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcPath));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destPath))) {
int len;
while ((len = bis.read(buffer)) != -1) {
bos.write(buffer, 0, len);
}
}
}
// 测试
public static void main(String[] args) throws IOException {
// 复制文本文件
copyTextFile("src/original.txt", "src/copy_text.txt");
// 复制图片文件
copyAnyFile("src/original.jpg", "src/copy_image.jpg");
}
}
七、总结
- 文本文件复制优先用字符缓冲流,便捷高效;
- 任意文件复制必须用字节缓冲流,通用性强;
- 缓冲流是 Java IO 性能优化的关键,必须掌握;
- try-with-resources 是 Java IO 编程的规范写法,能避免资源泄漏。
