当前位置: 首页 > ds >正文

Java 实现目录递归拷贝

Java 实现目录递归拷贝

目录递归拷贝是指将一个目录及其所有子目录和文件完整复制到另一个位置。下面我将详细介绍如何使用 Java 的 File 类实现这一功能,并提供优化版本(NIO.2)和常见问题解决方案。


1. 基于 File 类的递归拷贝实现

核心思路

  1. 如果是文件 → 直接拷贝

  2. 如果是目录 → 创建目标目录 → 递归拷贝其内容

完整代码实现

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. 递归拷贝的注意事项

  1. 符号链接:NIO.2 的 Files.walkFileTree() 会自动处理,传统方式需要额外判断

  2. 异常处理:确保关闭流资源(用 try-with-resources)

  3. 内存管理:拷贝超大文件时避免一次性读取全部内容


6. 扩展练习

  1. 添加进度显示:在拷贝时打印已完成文件数/总文件数

  2. 实现断点续传:记录已拷贝文件,程序重启后跳过已处理部分

  3. 多线程拷贝:对子目录使用线程池加速(注意线程安全)

http://www.xdnf.cn/news/2334.html

相关文章:

  • Agent2Agent
  • MyBatis 插件开发的完整详细例子
  • Python 实现将图像发送到指定的 API 进行推理
  • docker配置mysql遇到的问题:网络连接超时、启动mysql失败、navicat无法远程连接mysql
  • 跨端时代的全栈新范式:React Server Components深度集成指南
  • 智能赋能与精准评估:大语言模型在自动作文评分中的效度验证及改进路径
  • JS toFixed的坑以及四舍五入实现方法
  • 可靠传输的守护者:揭开计算机网络传输层的奥秘
  • 【C++】14.容器适配器 | stack | queue | 仿函数 | priority_queue
  • 迷宫问题演示
  • Kafka + Kafka-UI
  • Python dotenv 使用指南:轻松管理项目环境变量
  • 【SSH 端口转发】通过SSH端口转发实现访问远程服务器的 tensorboard
  • 什么是函数依赖中的 **自反律(Reflexivity)**、**增广律(Augmentation)** 和 **传递律(Transitivity)?
  • Eclipse 插件开发 2
  • RASP技术在DevOps中的安全应用
  • Python-MCPServer开发
  • 产业观察:哈飞空客2025.4.26
  • 【MATLAB】基于RSSI原理的Wi-Fi定位程序,N个锚点(数量可自适应)、三维空间,轨迹使用UKF进行滤波,附完整代码(订阅专栏后可直接复制粘贴)
  • 100亿补贴不是终点:京东外卖在下一盘颠覆即时零售的大棋
  • w307MES生产制造执行系统设计与实现
  • SEO新手快速上手核心步骤
  • 【Android Compose】焦点管理
  • AWS中国区ICP备案全攻略:流程、注意事项与最佳实践
  • python 画折线统计图
  • 华为OD机试真题——二维伞的雨滴效应(2025A卷:200分)Java/python/JavaScript/C/C++/GO最佳实现
  • element ui el-col的高度不一致导致换行
  • AQS条件队列源码详细剖析
  • FPGA 100G UDP纯逻辑协议栈
  • 【C语言】柔性数组