当然可以!这里提供一个实用的Java文件复制工具类,包含多种复制方式和详细的代码注释:

import java.io.*;
import java.nio.channels.FileChannel;
import java.nio.file.*;
/**
* 文件复制工具类
* 包含多种文件复制方式:字节流、字符流、NIO通道等
*/
public class FileCopyTool {
/**
* 使用传统字节流复制文件(基础版)
* @param source 源文件路径
* @param target 目标文件路径
* @throws IOException IO异常
*/
public static void copyByStream(String source, String target) throws IOException {
// 验证源文件是否存在
File sourceFile = new File(source);
if (!sourceFile.exists()) {
throw new FileNotFoundException("源文件不存在: " + source);
}
// 确保目标目录存在
File targetFile = new File(target);
File parentDir = targetFile.getParentFile();
if (parentDir != null && !parentDir.exists()) {
parentDir.mkdirs();
}
// 使用try-with-resources自动关闭资源
try (FileInputStream fis = new FileInputStream(sourceFile);
FileOutputStream fos = new FileOutputStream(targetFile);
BufferedInputStream bis = new BufferedInputStream(fis);
BufferedOutputStream bos = new BufferedOutputStream(fos)) {
byte[] buffer = new byte[8192]; // 8KB缓冲区
int bytesRead;
// 循环读取并写入
while ((bytesRead = bis.read(buffer)) != -1) {
bos.write(buffer, 0, bytesRead);
}
bos.flush(); // 强制刷新缓冲区
}
}
/**
* 使用NIO FileChannel复制文件(推荐用于大文件)
* @param source 源文件路径
* @param target 目标文件路径
* @throws IOException IO异常
*/
public static void copyByChannel(String source, String target) throws IOException {
Path sourcePath = Paths.get(source);
Path targetPath = Paths.get(target);
// 确保目标目录存在
Files.createDirectories(targetPath.getParent());
// 使用FileChannel进行高效的零拷贝传输
try (FileChannel sourceChannel = FileChannel.open(sourcePath, StandardOpenOption.READ);
FileChannel targetChannel = FileChannel.open(targetPath,
StandardOpenOption.CREATE, StandardOpenOption.WRITE)) {
long position = 0;
long size = sourceChannel.size();
// 使用transferTo实现零拷贝,减少数据在内核和用户空间之间的拷贝
while (position < size) {
position += sourceChannel.transferTo(position, size - position, targetChannel);
}
}
}
/**
* 使用NIO Files工具类复制(最简单方式)
* @param source 源文件路径
* @param target 目标文件路径
* @param replaceExisting 是否覆盖已存在的文件
* @throws IOException IO异常
*/
public static void copyByFiles(String source, String target, boolean replaceExisting) throws IOException {
Path sourcePath = Paths.get(source);
Path targetPath = Paths.get(target);
// 创建目标目录
Files.createDirectories(targetPath.getParent());
// 复制选项
CopyOption[] options = replaceExisting
? new CopyOption[] { StandardCopyOption.REPLACE_EXISTING }
: new CopyOption[] {};
// 使用Files.copy()方法
Files.copy(sourcePath, targetPath, options);
}
/**
* 带进度显示的文件复制(使用字节流)
* @param source 源文件路径
* @param target 目标文件路径
* @throws IOException IO异常
*/
public static void copyWithProgress(String source, String target) throws IOException {
File sourceFile = new File(source);
if (!sourceFile.exists()) {
throw new FileNotFoundException("源文件不存在: " + source);
}
long totalBytes = sourceFile.length();
long copiedBytes = 0;
// 确保目标目录存在
File targetFile = new File(target);
File parentDir = targetFile.getParentFile();
if (parentDir != null && !parentDir.exists()) {
parentDir.mkdirs();
}
try (FileInputStream fis = new FileInputStream(sourceFile);
FileOutputStream fos = new FileOutputStream(targetFile);
BufferedInputStream bis = new BufferedInputStream(fis);
BufferedOutputStream bos = new BufferedOutputStream(fos)) {
byte[] buffer = new byte[8192];
int bytesRead;
int progress = 0;
int lastProgress = 0;
System.out.print("复制进度: ");
while ((bytesRead = bis.read(buffer)) != -1) {
bos.write(buffer, 0, bytesRead);
copiedBytes += bytesRead;
// 计算并显示进度
progress = (int) (copiedBytes * 100 / totalBytes);
if (progress > lastProgress) {
System.out.print("\r复制进度: " + progress + "%");
lastProgress = progress;
}
}
bos.flush();
System.out.println("\r复制进度: 100% - 完成!");
}
}
/**
* 递归复制目录
* @param sourceDir 源目录路径
* @param targetDir 目标目录路径
* @throws IOException IO异常
*/
public static void copyDirectory(String sourceDir, String targetDir) throws IOException {
File source = new File(sourceDir);
File target = new File(targetDir);
if (!source.exists()) {
throw new FileNotFoundException("源目录不存在: " + sourceDir);
}
if (!source.isDirectory()) {
throw new IllegalArgumentException("源路径必须是目录: " + sourceDir);
}
// 创建目标目录
if (!target.exists()) {
target.mkdirs();
}
// 获取源目录下的所有文件
File[] files = source.listFiles();
if (files == null) {
throw new IOException("无法读取目录: " + sourceDir);
}
for (File file : files) {
String targetPath = targetDir + File.separator + file.getName();
if (file.isDirectory()) {
// 递归复制子目录
copyDirectory(file.getAbsolutePath(), targetPath);
} else {
// 复制文件
copyByStream(file.getAbsolutePath(), targetPath);
}
}
}
/**
* 主方法 - 演示使用
*/
public static void main(String[] args) {
try {
// 测试文件复制
String sourceFile = "test.txt";
String targetFile = "test_copy.txt";
// 创建测试文件
try (FileWriter writer = new FileWriter(sourceFile)) {
writer.write("Hello, File Copy Tool!\n");
writer.write("This is a test file.\n");
writer.write("包含中文字符测试。\n");
}
System.out.println("=== 字节流复制 ===");
copyByStream(sourceFile, "test_stream_copy.txt");
System.out.println("\n=== NIO Channel复制 ===");
copyByChannel(sourceFile, "test_channel_copy.txt");
System.out.println("\n=== Files工具类复制 ===");
copyByFiles(sourceFile, "test_files_copy.txt", true);
System.out.println("\n=== 带进度复制 ===");
copyWithProgress(sourceFile, "test_progress_copy.txt");
System.out.println("\n=== 测试目录复制 ===");
// 创建测试目录
new File("testDir").mkdirs();
try (FileWriter writer = new FileWriter("testDir/test1.txt")) {
writer.write("File 1 content");
}
try (FileWriter writer = new FileWriter("testDir/test2.txt")) {
writer.write("File 2 content");
}
copyDirectory("testDir", "testDir_copy");
System.out.println("所有复制操作完成!");
} catch (IOException e) {
System.err.println("复制失败: " + e.getMessage());
e.printStackTrace();
}
}
}
主要功能特点:
-
多种复制方式:
- 传统字节流复制
- NIO Channel零拷贝复制(适合大文件)
- Files工具类简单复制
-
高级功能:
- 支持进度显示
- 递归复制整个目录
- 自动创建目标目录结构
-
最佳实践:
- 使用缓冲流提高性能
- try-with-resources自动资源管理
- 合理的缓冲区大小(8KB)
- 完善的异常处理
使用建议:
- 大文件推荐使用
copyByChannel()的零拷贝方式 - 简单场景使用
copyByFiles()最方便 - 需要进度显示时使用
copyWithProgress() - 复制目录使用
copyDirectory()