Java 实现目录递归拷贝
Java 实现目录递归拷贝
目录递归拷贝是指将一个目录及其所有子目录和文件完整复制到另一个位置。下面我将详细介绍如何使用 Java 的 File
类实现这一功能,并提供优化版本(NIO.2)和常见问题解决方案。
1. 基于 File
类的递归拷贝实现
核心思路
-
如果是文件 → 直接拷贝
-
如果是目录 → 创建目标目录 → 递归拷贝其内容
完整代码实现
java
import java.io.*;public class DirectoryCopy {public static void main(String[] args) {File srcDir = new File("C:/source");File destDir = new File("C:/destination");copyDirectory(srcDir, destDir);}public static void copyDirectory(File source, File target) throws IOException {if (!target.exists()) {target.mkdirs(); // 创建目标目录}for (File file : source.listFiles()) {File destFile = new File(target, file.getName());if (file.isDirectory()) {copyDirectory(file, destFile); // 递归拷贝子目录} else {copyFile(file, destFile); // 拷贝文件}}}private static void copyFile(File source, File dest) throws IOException {try (InputStream in = new FileInputStream(source);OutputStream out = new FileOutputStream(dest)) {byte[] buffer = new byte[1024];int length;while ((length = in.read(buffer)) > 0) {out.write(buffer, 0, length);}}}
}
2. 使用 NIO.2(Java 7+ 推荐)
NIO.2 提供了更简洁高效的 API(Files.copy()
):
java
import java.nio.file.*;public class NioDirectoryCopy {public static void main(String[] args) throws IOException {Path source = Paths.get("C:/source");Path target = Paths.get("C:/destination");copyDirectory(source, target);}public static void copyDirectory(Path source, Path target) throws IOException {Files.walkFileTree(source, new SimpleFileVisitor<Path>() {@Overridepublic FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {Path relativePath = source.relativize(dir);Path destPath = target.resolve(relativePath);Files.createDirectories(destPath); // 创建目标目录return FileVisitResult.CONTINUE;}@Overridepublic FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {Path relativePath = source.relativize(file);Path destPath = target.resolve(relativePath);Files.copy(file, destPath, StandardCopyOption.REPLACE_EXISTING);return FileVisitResult.CONTINUE;}});}
}
优势:
-
自动处理符号链接
-
支持原子操作和文件属性保留
-
更简洁的异常处理
3. 关键问题与解决方案
问题1:文件已存在
-
解决:添加覆盖选项
java
// File 类方式
if (destFile.exists()) destFile.delete();// NIO 方式
Files.copy(file, destPath, StandardCopyOption.REPLACE_EXISTING);
问题2:大文件拷贝性能优化
-
解决:使用缓冲流(Buffer)或 NIO 的
FileChannel
java
// 使用 FileChannel(零拷贝技术)
try (FileChannel inChannel = new FileInputStream(source).getChannel();FileChannel outChannel = new FileOutputStream(dest).getChannel()) {inChannel.transferTo(0, inChannel.size(), outChannel);
}
问题3:权限保留
-
NIO 解决方案:
java
Files.copy(file, destPath, StandardCopyOption.COPY_ATTRIBUTES);
4. 性能对比
方法 | 适用场景 | 优点 | 缺点 |
---|---|---|---|
File + 字节流 | Java 6 及以下版本 | 兼容性好 | 代码冗长,性能较低 |
Files.copy() | Java 7+ 常规需求 | 简洁高效 | 不兼容旧 Java 版本 |
FileChannel | 大文件拷贝 | 零拷贝,性能最佳 | 代码稍复杂 |
5. 递归拷贝的注意事项
-
符号链接:NIO.2 的
Files.walkFileTree()
会自动处理,传统方式需要额外判断 -
异常处理:确保关闭流资源(用 try-with-resources)
-
内存管理:拷贝超大文件时避免一次性读取全部内容
6. 扩展练习
-
添加进度显示:在拷贝时打印已完成文件数/总文件数
-
实现断点续传:记录已拷贝文件,程序重启后跳过已处理部分
-
多线程拷贝:对子目录使用线程池加速(注意线程安全)