FileCopyUtil.java 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. package J20250805.demo01;
  2. import java.io.*;
  3. import java.rmi.RemoteException;
  4. import java.util.ArrayList;
  5. import java.util.Arrays;
  6. import java.util.List;
  7. import java.util.concurrent.*;
  8. import java.util.concurrent.atomic.AtomicInteger;
  9. /**
  10. * @author WanJl
  11. * @version 1.0
  12. * @title FileCopyUtil
  13. * @description
  14. * **文件夹拷贝工具**
  15. * 需求:
  16. * - 设计`FileCopyUtil`类,包含`copyDirectory(String srcDir, String destDir)`方法
  17. * - 使用多线程并发拷贝目录下的文件(子目录需递归处理)
  18. * - 利用`BufferedInputStream`和`BufferedOutputStream`提高 IO 效率
  19. * - 统计总拷贝文件数和耗时,通过`System.out`输出结果
  20. * @create 2025/8/5
  21. */
  22. public class FileCopyUtil {
  23. //线程安全的计数器,用来统计拷贝的文件总数
  24. private final AtomicInteger copyFileCount=new AtomicInteger();
  25. private ExecutorService executorService;
  26. /**
  27. * 拷贝目录的方法--在这里进行多线程操作
  28. * @param srcDir 源目录路径
  29. * @param destDir 目标目录路径
  30. */
  31. public void copyDirectory(String srcDir, String destDir) throws IOException, InterruptedException {
  32. File srcDirectory=new File(srcDir);
  33. File destDirectory=new File(destDir);
  34. //验证目录是否有效,
  35. if (!srcDirectory.exists()){
  36. throw new FileNotFoundException("源目录不存在"+srcDir);
  37. }
  38. //记录开始时间
  39. long startTime = System.currentTimeMillis();
  40. //初始化线程池
  41. int threadCount=Runtime.getRuntime().availableProcessors()*2;
  42. executorService= Executors.newFixedThreadPool(3);
  43. try{
  44. //处理目录复制
  45. copyDir(srcDirectory,destDirectory);
  46. //关闭线程池并且等待所有的任务都完成
  47. executorService.shutdown();
  48. if (!executorService.awaitTermination(1, TimeUnit.SECONDS)){
  49. executorService.shutdownNow();
  50. }
  51. }finally {
  52. if (!executorService.isTerminated()){
  53. executorService.shutdownNow();
  54. }
  55. }
  56. //计算耗时并且输出统计结果
  57. long endTime = System.currentTimeMillis();
  58. long time=endTime-startTime;
  59. System.out.println("目录拷贝完成");
  60. System.out.println("总拷贝文件数:"+copyFileCount.get());
  61. System.out.println("总耗时"+time+"毫秒");
  62. }
  63. /**
  64. * 多线程中每个线程要执行的拷贝任务
  65. * @param srcDir
  66. * @param destDir
  67. */
  68. private void copyDir(File srcDir, File destDir) throws IOException,InterruptedException {
  69. //创建目标目录对象
  70. if (!destDir.exists()&&!destDir.mkdirs()){
  71. throw new IOException("无法创建目标目录"+destDir.getAbsolutePath());
  72. }
  73. //获取源目录中的所有的文件和子目录
  74. File[] files = srcDir.listFiles();
  75. System.out.println(Arrays.toString(files));
  76. if (files==null){
  77. throw new IOException("无法访问目录内容"+srcDir.getAbsolutePath());
  78. }
  79. //任务集合
  80. List<Future<?>> futures=new ArrayList<>();
  81. //处理目录中每个文件和文件夹
  82. for (File file:files){
  83. //在目标目录位置创建文件或子目录
  84. File destFile = new File(destDir, file.getName());
  85. if (file.isDirectory()){
  86. //递归处理子目录
  87. copyDir(file,destFile);
  88. }else {
  89. //提交文件拷贝任务到线程池
  90. Future<?> future=executorService.submit(()-> {
  91. try {
  92. copyFile(file,destFile);
  93. } catch (IOException e) {
  94. e.printStackTrace();
  95. }
  96. });
  97. //将任务放入集合
  98. futures.add(future);
  99. }
  100. }
  101. //等所有的文件拷贝任务都完成后
  102. for (Future<?> future:futures){
  103. try {
  104. future.get();
  105. }catch (ExecutionException e) {
  106. //处理任务过程中如果出现问题则也抛出异常
  107. Throwable cause = e.getCause();
  108. if (cause instanceof IOException){
  109. throw (IOException) cause;
  110. }else {
  111. throw new RemoteException("文件拷贝失败",cause);
  112. }
  113. }
  114. }
  115. }
  116. /**
  117. * 复制单个文件,使用缓冲流提高效率
  118. * @param srcFile
  119. * @param destFile
  120. */
  121. private void copyFile(File srcFile, File destFile) throws IOException {
  122. try(BufferedInputStream bis=new BufferedInputStream(new FileInputStream(srcFile));
  123. BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream(destFile))) {
  124. //字节缓冲区
  125. byte[] buffer=new byte[8192];
  126. int byteRead;
  127. //读取数据并且写入数据
  128. while ((byteRead=bis.read(buffer))!=-1){
  129. bos.write(buffer,0,byteRead);
  130. }
  131. //确保所有的数据都写入到磁盘
  132. bos.flush();
  133. //递增文件计数器
  134. copyFileCount.incrementAndGet();
  135. }
  136. }
  137. public static void main(String[] args) throws IOException, InterruptedException {
  138. FileCopyUtil fileCopyUtil=new FileCopyUtil();
  139. fileCopyUtil.copyDirectory("D:\\myCode\\battle_city","D:\\MavenRepository111");
  140. }
  141. }