123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152 |
- package J20250805.demo01;
- import java.io.*;
- import java.rmi.RemoteException;
- import java.util.ArrayList;
- import java.util.Arrays;
- import java.util.List;
- import java.util.concurrent.*;
- import java.util.concurrent.atomic.AtomicInteger;
- /**
- * @author WanJl
- * @version 1.0
- * @title FileCopyUtil
- * @description
- * **文件夹拷贝工具**
- * 需求:
- * - 设计`FileCopyUtil`类,包含`copyDirectory(String srcDir, String destDir)`方法
- * - 使用多线程并发拷贝目录下的文件(子目录需递归处理)
- * - 利用`BufferedInputStream`和`BufferedOutputStream`提高 IO 效率
- * - 统计总拷贝文件数和耗时,通过`System.out`输出结果
- * @create 2025/8/5
- */
- public class FileCopyUtil {
- //线程安全的计数器,用来统计拷贝的文件总数
- private final AtomicInteger copyFileCount=new AtomicInteger();
- private ExecutorService executorService;
- /**
- * 拷贝目录的方法--在这里进行多线程操作
- * @param srcDir 源目录路径
- * @param destDir 目标目录路径
- */
- public void copyDirectory(String srcDir, String destDir) throws IOException, InterruptedException {
- File srcDirectory=new File(srcDir);
- File destDirectory=new File(destDir);
- //验证目录是否有效,
- if (!srcDirectory.exists()){
- throw new FileNotFoundException("源目录不存在"+srcDir);
- }
- //记录开始时间
- long startTime = System.currentTimeMillis();
- //初始化线程池
- int threadCount=Runtime.getRuntime().availableProcessors()*2;
- executorService= Executors.newFixedThreadPool(3);
- try{
- //处理目录复制
- copyDir(srcDirectory,destDirectory);
- //关闭线程池并且等待所有的任务都完成
- executorService.shutdown();
- if (!executorService.awaitTermination(1, TimeUnit.SECONDS)){
- executorService.shutdownNow();
- }
- }finally {
- if (!executorService.isTerminated()){
- executorService.shutdownNow();
- }
- }
- //计算耗时并且输出统计结果
- long endTime = System.currentTimeMillis();
- long time=endTime-startTime;
- System.out.println("目录拷贝完成");
- System.out.println("总拷贝文件数:"+copyFileCount.get());
- System.out.println("总耗时"+time+"毫秒");
- }
- /**
- * 多线程中每个线程要执行的拷贝任务
- * @param srcDir
- * @param destDir
- */
- private void copyDir(File srcDir, File destDir) throws IOException,InterruptedException {
- //创建目标目录对象
- if (!destDir.exists()&&!destDir.mkdirs()){
- throw new IOException("无法创建目标目录"+destDir.getAbsolutePath());
- }
- //获取源目录中的所有的文件和子目录
- File[] files = srcDir.listFiles();
- System.out.println(Arrays.toString(files));
- if (files==null){
- throw new IOException("无法访问目录内容"+srcDir.getAbsolutePath());
- }
- //任务集合
- List<Future<?>> futures=new ArrayList<>();
- //处理目录中每个文件和文件夹
- for (File file:files){
- //在目标目录位置创建文件或子目录
- File destFile = new File(destDir, file.getName());
- if (file.isDirectory()){
- //递归处理子目录
- copyDir(file,destFile);
- }else {
- //提交文件拷贝任务到线程池
- Future<?> future=executorService.submit(()-> {
- try {
- copyFile(file,destFile);
- } catch (IOException e) {
- e.printStackTrace();
- }
- });
- //将任务放入集合
- futures.add(future);
- }
- }
- //等所有的文件拷贝任务都完成后
- for (Future<?> future:futures){
- try {
- future.get();
- }catch (ExecutionException e) {
- //处理任务过程中如果出现问题则也抛出异常
- Throwable cause = e.getCause();
- if (cause instanceof IOException){
- throw (IOException) cause;
- }else {
- throw new RemoteException("文件拷贝失败",cause);
- }
- }
- }
- }
- /**
- * 复制单个文件,使用缓冲流提高效率
- * @param srcFile
- * @param destFile
- */
- private void copyFile(File srcFile, File destFile) throws IOException {
- try(BufferedInputStream bis=new BufferedInputStream(new FileInputStream(srcFile));
- BufferedOutputStream bos=new BufferedOutputStream(new FileOutputStream(destFile))) {
- //字节缓冲区
- byte[] buffer=new byte[8192];
- int byteRead;
- //读取数据并且写入数据
- while ((byteRead=bis.read(buffer))!=-1){
- bos.write(buffer,0,byteRead);
- }
- //确保所有的数据都写入到磁盘
- bos.flush();
- //递增文件计数器
- copyFileCount.incrementAndGet();
- }
- }
- public static void main(String[] args) throws IOException, InterruptedException {
- FileCopyUtil fileCopyUtil=new FileCopyUtil();
- fileCopyUtil.copyDirectory("D:\\myCode\\battle_city","D:\\MavenRepository111");
- }
- }
|