一、作业概述
本次作业要求实现文件复制的四种不同方式:
序号 方式 核心类 适用场景
1 文本文件复制 FileReader / FileWriter 仅文本文件
2 字符缓冲流 BufferedReader / BufferedWriter 文本文件(最常用)
3 任意文件复制 FileInputStream / FileOutputStream 任意类型文件
4 字节缓冲流 BufferedInputStream / BufferedOutputStream 任意文件(万能复制)
核心原理:从一个文件中读取数据,写入到另一个文件中。
二、基础知识回顾
2.1 Java IO流分类
text
Java IO流
├── 字节流(处理所有文件)
│ ├── InputStream(输入流)—— FileInputStream
│ ├── OutputStream(输出流)—— FileOutputStream
│ ├── BufferedInputStream(缓冲输入流)
│ └── BufferedOutputStream(缓冲输出流)
└── 字符流(仅处理文本文件)
├── Reader(输入流)—— FileReader
├── Writer(输出流)—— FileWriter
├── BufferedReader(缓冲输入流)
└── BufferedWriter(缓冲输出流)
2.2 字符流 vs 字节流
对比项 字符流 字节流
处理单位 字符(16-bit) 字节(8-bit)
适用文件 文本文件(.txt, .java, .csv) 任意文件(图片、视频、音频等)
核心类 Reader, Writer InputStream, OutputStream
是否支持中文 是 需要手动处理编码
2.3 缓冲流的作用
特性 无缓冲流 有缓冲流
读取方式 每次读一个字节/字符 一次读一批数据到内存缓冲区
IO次数 频繁 减少
性能 较低 较高
特有方法 无 readLine()(字符缓冲流)
三、方式一:文本文件复制(字符流)
3.1 实现原理
使用 FileReader 读取文本文件,FileWriter 写入到目标文件。一次读取一个字符数组,提高效率。
3.2 代码实现
以下是整理后的代码块,符合Markdown 格式要求:
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
/**
方式一:文本文件复制
使用字符流 FileReader/FileWriter
适用于:.txt, .java, .csv 等文本文件
*/
public class TextFileCopy {
public static void main(String[] args) {
String sourceFile = “source.txt”;
String destFile = “dest_text.txt”;
try {
copyFile(sourceFile, destFile);
System.out.println(“文件复制成功!”);
System.out.println(“源文件:” + sourceFile);
System.out.println(“目标文件:” + destFile);
} catch (IOException e) {
System.out.println(“文件复制失败:” + e.getMessage());
e.printStackTrace();
}
}public static void copyFile(String sourcePath, String destPath) throws IOException {
try (FileReader fr = new FileReader(sourcePath);
FileWriter fw = new FileWriter(destPath)) {
char[] buffer = new char[1024];
int len;
while ((len = fr.read(buffer)) != -1) {
fw.write(buffer, 0, len);
}
System.out.println(“已复制 “ + len + “ 个字符”);
}
}
}
AI写代码
java
运行
3.3 代码解释
代码 说明
FileReader fr = new FileReader(sourcePath) 创建文件字符输入流,用于读取源文件
FileWriter fw = new FileWriter(destPath) 创建文件字符输出流,用于写入目标文件
char[] buffer = new char[1024] 创建字符数组缓冲区,一次读取1024个字符
fr.read(buffer) 从源文件读取数据到缓冲区,返回实际读取的字符数
fw.write(buffer, 0, len) 将缓冲区中的数据写入目标文件
try-with-resources 自动关闭流资源,不需要手动调用close()
3.4 运行效果
假设 source.txt 内容为:
text
Hello Java!
你好,世界!
这是文件复制测试。
复制后的 dest_text.txt 内容完全相同。
四、方式二:字符缓冲流(最常用)
4.1 实现原理
使用 BufferedReader 和 BufferedWriter 包装基本的字符流,提供缓冲功能,提高读写效率。BufferedReader 提供了 readLine() 方法,可以一次读取一行文本,非常方便。
4.2 代码实现
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
/**
方式二:字符缓冲流复制文本文件
使用 BufferedReader/BufferedWriter
特点:最常用、支持按行读取、性能高
*/
public class BufferedTextFileCopy {public static void main(String[] args) {
String sourceFile = “source.txt”;
String destFile = “dest_buffered.txt”;
try {
copyFile(sourceFile, destFile);
System.out.println(“文件复制成功!”);
} catch (IOException e) {
System.out.println(“文件复制失败:” + e.getMessage());
}
}/**
- 使用缓冲流复制文本文件
- @param sourcePath 源文件路径
- @param destPath 目标文件路径
- @throws IOException IO异常
*/
public static void copyFile(String sourcePath, String destPath) throws IOException {
// 使用 try-with-resources 自动关闭资源
try (BufferedReader br = new BufferedReader(new FileReader(sourcePath));
BufferedWriter bw = new BufferedWriter(new FileWriter(destPath))) {
String line;
int lineCount = 0;
// 按行读取,逐行写入
while ((line = br.readLine()) != null) {
bw.write(line);
bw.newLine(); // 写入换行符
lineCount++;
}
System.out.println(“共复制 “ + lineCount + “ 行”);
}
}
}
AI写代码
java
运行
4.3 为什么是最常用的?
优点 说明
按行读取 readLine() 方法非常方便处理文本
缓冲性能 减少实际IO次数,提高效率
编码友好 正确处理中文字符
代码简洁 逻辑清晰,易于理解和维护
4.4 代码解释
代码 说明
new BufferedReader(new FileReader(…)) 在 FileReader 外层包装缓冲流
br.readLine() 读取一行文本(不包含换行符),返回 null 表示读到文件末尾
bw.write(line) 写入一行文本
bw.newLine() 写入系统相关的换行符(Windows: \r\n, Linux: \n)
五、方式三:任意文件复制(字节流)
5.1 实现原理
使用 FileInputStream 和 FileOutputStream 处理字节数据。这种方式可以复制任意类型的文件,因为所有文件在计算机中本质上都是字节序列。
5.2 代码实现
以下是转换后的代码块格式:
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
/**
方式三:任意文件复制
使用字节流 FileInputStream/FileOutputStream
适用于:图片、视频、音频、压缩包等任意文件
*/
public class AnyFileCopy {
public static void main(String[] args) {
// 示例:复制图片文件
String sourceFile = “photo.jpg”;
String destFile = “photo_copy.jpg”;
// 示例:复制视频文件
// String sourceFile = “video.mp4”;
// String destFile = “video_copy.mp4”;
try {
copyFile(sourceFile, destFile);
System.out.println(“文件复制成功!”);
} catch (IOException e) {
System.out.println(“文件复制失败:” + e.getMessage());
}
}/**
- 使用字节流复制任意文件
- @param sourcePath 源文件路径
- @param destPath 目标文件路径
- @throws IOException IO异常
*/
public static void copyFile(String sourcePath, String destPath) throws IOException {
try (FileInputStream fis = new FileInputStream(sourcePath);
FileOutputStream fos = new FileOutputStream(destPath)) {
// 字节数组缓冲区,一次读取1024个字节
byte[] buffer = new byte[1024];
int len;
long totalBytes = 0;
while ((len = fis.read(buffer)) != -1) {
fos.write(buffer, 0, len);
totalBytes += len;
}
System.out.println(“共复制 “ + totalBytes + “ 字节”);
System.out.println(“约 “ + (totalBytes / 1024) + “ KB”);
}
}
}
AI写代码
java
运行
5.3 支持的任意文件类型
文件类型 扩展名 是否支持
文本文件 .txt, .java, .xml, .json 支持
图片 .jpg, .png, .gif, .bmp 支持
视频 .mp4, .avi, .mkv, .flv 支持
音频 .mp3, .wav, .flac 支持
压缩包 .zip, .rar, .7z 支持
可执行文件 .exe, .dll 支持
5.4 字节流 vs 字符流选择
if (fileType == 文本文件) {
// 使用字符流(方便处理文本)
useReaderWriter();
} else {
// 使用字节流(万能)
useInputStreamOutputStream();
}
AI写代码
java
运行
六、方式四:字节缓冲流(万能复制)
6.1 实现原理
使用 BufferedInputStream 和 BufferedOutputStream 包装基本的字节流,提供内部缓冲区,减少实际IO次数,是最通用、性能最好的文件复制方式。
6.2 代码实现
以下是转换后的代码块格式:
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class BufferedAnyFileCopy {
public static void main(String[] args) {
copyFile(“photo.jpg”, “photo_buffered_copy.jpg”);
}
public static boolean copyFile(String sourcePath, String destPath) {
if (sourcePath == null || destPath == null) {
System.err.println("文件路径不能为空");
return false;
}
long startTime = System.currentTimeMillis();
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(sourcePath));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destPath))) {
byte[] buffer = new byte[8192];
int len;
long totalBytes = 0;
while ((len = bis.read(buffer)) != -1) {
bos.write(buffer, 0, len);
totalBytes += len;
}
bos.flush();
long endTime = System.currentTimeMillis();
long duration = endTime - startTime;
System.out.println("========== 复制完成 ==========");
System.out.println("源文件:" + sourcePath);
System.out.println("目标文件:" + destPath);
System.out.println("文件大小:" + formatSize(totalBytes));
System.out.println("耗时:" + duration + " 毫秒");
System.out.println("================================");
return true;
} catch (IOException e) {
System.err.println("文件复制失败:" + e.getMessage());
return false;
}
}
private static String formatSize(long bytes) {
if (bytes < 1024) {
return bytes + " B";
} else if (bytes < 1024 * 1024) {
return String.format("%.2f KB", bytes / 1024.0);
} else if (bytes < 1024 * 1024 * 1024) {
return String.format("%.2f MB", bytes / (1024.0 * 1024));
} else {
return String.format("%.2f GB", bytes / (1024.0 * 1024 * 1024));
}
}
}
AI写代码
java
运行
6.3 为什么是“万能复制”?
特点 说明
文件类型无关 无论是文本、图片、视频还是可执行文件,都能正确处理
编码无关 按字节处理,不涉及编码问题
性能优化 内置缓冲区,减少IO次数
大文件支持 边读边写,不会一次性加载整个文件到内存
6.4 性能对比测试
/**
性能对比测试
比较四种复制方式的效率
*/
public class PerformanceTest {
public static void main(String[] args) {
String testFile = “large_file.txt”; // 假设有一个10MB的文件
// 测试四种方式的复制时间
testMethod(“方式一:字符流”, () -> {
TextFileCopy.copyFile(testFile, “test1.txt”);
});
testMethod(“方式二:字符缓冲流”, () -> {
BufferedTextFileCopy.copyFile(testFile, “test2.txt”);
});
testMethod(“方式三:字节流”, () -> {
AnyFileCopy.copyFile(testFile, “test3.txt”);
});
testMethod(“方式四:字节缓冲流”, () -> {
BufferedAnyFileCopy.copyFile(testFile, “test4.txt”);
});
}private static void testMethod(String name, Runnable method) {
long start = System.nanoTime();
method.run();
long end = System.nanoTime();
System.out.println(name + “ 耗时:” + (end - start) / 1000000 + “ ms”);
}
}
AI写代码
java
运行
典型运行结果(复制10MB文件):
text
方式一:字符流 耗时:450 ms
方式二:字符缓冲流 耗时:120 ms ← 比无缓冲快3-4倍
方式三:字节流 耗时:480 ms
方式四:字节缓冲流 耗时:100 ms ← 最快,万能选择
七、四种方式对比总结
对比项 方式一 方式二 方式三 方式四
核心类 FileReader/Writer BufferedReader/Writer FileInput/OutputStream BufferedInput/OutputStream
处理单位 字符 字符(按行) 字节 字节
适用文件 仅文本 仅文本 任意文件 任意文件
缓冲支持 手动数组 内置缓冲 手动数组 内置缓冲
性能 中 高 中 最高
编码问题 自动处理 自动处理 需注意 需注意
推荐场景 小文本文件 文本文件(最常用) 任意小文件 万能复制(推荐)
选择建议:
复制文本文件 → 用方式二(字符缓冲流)
复制任意文件(图片、视频等) → 用方式四(字节缓冲流)
简单小文件测试 → 方式一或方式三
生产环境 → 方式四
八、完整代码整合版
以下是一个完整的工具类,整合了四种复制方式:
import java.io.*;
/**
文件复制工具类
提供四种不同的文件复制方式
*/
public class FileCopyUtil {/**
- 方式一:字符流复制文本文件
*/
public static void copyByCharStream(String src, String dest) throws IOException {
try (FileReader fr = new FileReader(src);
FileWriter fw = new FileWriter(dest)) {
char[] buffer = new char[1024];
int len;
while ((len = fr.read(buffer)) != -1) {
fw.write(buffer, 0, len);
}
}
}
/**
- 方式二:字符缓冲流复制文本文件(推荐文本文件使用)
*/
public static void copyByBufferedCharStream(String src, String dest) throws IOException {
try (BufferedReader br = new BufferedReader(new FileReader(src));
BufferedWriter bw = new BufferedWriter(new FileWriter(dest))) {
String line;
while ((line = br.readLine()) != null) {
bw.write(line);
bw.newLine();
}
}
}
/**
- 方式三:字节流复制任意文件
*/
public static void copyByByteStream(String src, String dest) throws IOException {
try (FileInputStream fis = new FileInputStream(src);
FileOutputStream fos = new FileOutputStream(dest)) {
byte[] buffer = new byte[1024];
int len;
while ((len = fis.read(buffer)) != -1) {
fos.write(buffer, 0, len);
}
}
}
/**
- 方式四:字节缓冲流复制任意文件(万能复制,推荐)
*/
public static void copyByBufferedByteStream(String src, String dest) throws IOException {
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(src));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(dest))) {
byte[] buffer = new byte[8192];
int len;
while ((len = bis.read(buffer)) != -1) {
bos.write(buffer, 0, len);
}
bos.flush();
}
}
// 测试
public static void main(String[] args) {
try {
// 文本文件复制测试
copyByBufferedCharStream(“source.txt”, “dest.txt”);// 图片文件复制测试 copyByBufferedByteStream("photo.jpg", "photo_copy.jpg"); System.out.println("所有文件复制完成!"); } catch (IOException e) { e.printStackTrace(); }}
- 方式一:字符流复制文本文件
}
AI写代码
java
运行
九、常见问题与解决方案
9.1 文件找不到异常(FileNotFoundException)
// 错误示例
FileReader fr = new FileReader(“nonexistent.txt”);
// 解决方案1:检查文件路径是否正确
// 解决方案2:使用绝对路径
FileReader fr = new FileReader(“D:/project/files/source.txt”);
// 解决方案3:先判断文件是否存在
File file = new File(“source.txt”);
if (!file.exists()) {
System.out.println(“文件不存在:” + file.getAbsolutePath());
return;
}
AI写代码
java
运行
9.2 中文乱码问题
// 问题:使用字节流读取中文文本文件可能出现乱码
// 解决:指定正确的字符集编码
// 方式一:使用字符流(默认使用系统编码)
BufferedReader br = new BufferedReader(new FileReader(“source.txt”));
// 方式二:指定编码(推荐)
BufferedReader br = new BufferedReader(
new InputStreamReader(new FileInputStream(“source.txt”), “UTF-8”));
AI写代码
java
运行
9.3 大文件复制内存 溢出
// 错误做法:一次性读取整个文件
byte[] allBytes = fis.readAllBytes(); // 大文件会内存溢出
// 正确做法:边读边写,使用缓冲区
byte[] buffer = new byte[8192];
int len;
while ((len = fis.read(buffer)) != -1) {
fos.write(buffer, 0, len);
}
AI写代码
java
运行
十、总结
10.1 核心知识点回顾
知识点 要点
字符流 用于文本文件,处理字符数据
字节流 用于任意文件,处理字节数据
缓冲流 提高IO性能,减少实际读写次数
try-with-resources 自动关闭流资源
缓冲区大小 通常 1024、2048、8192 字节