要用Java对单个文件拷贝的话,其实思路很简单,循环读取被拷贝文件,放入byte数组,然后写入目标文件。当然我们也可以借助现有的类去完成,如InputStream中的transferTo()方法就可以实现,其实我们查看源码就能看出来,其实官方的做法也是这样,只不过更严谨一些:

java复制文件到指定目录导致线程冲突 java拷贝目录_后端


那么我想拷贝多个文件呢?他们显示在不同的目录中,而且目标目录中还不一定存在,比如说,

现在我想把jdk8.0的官方源码src文件复制一份到D盘,现在这个文件在桌面,里面文件结构相当复杂了

java复制文件到指定目录导致线程冲突 java拷贝目录_java_02


那这如何做呢?我们当然可以借助组件,一些组件很好的帮我们实现了这个功能。但我喜欢先自己做一遍。

这里我分享我的思路以及实现结果:

全部代码如下:

package day_12_15.copy_dir;

import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author soberw
 * @Classname CopyDir
 * @Description 拷贝目录(包含目录里的文件)
 * @Date 2021-12-15 19:48
 */
public class CopyDir {
    //存放绝对路径以及文件名
    public static Map<String, String> map = new HashMap<>();

    /*
    思路是:

    先判断被拷贝的文件是否存在,在判断拷贝的文件是否存在,不存在则创建,
    然后采用递归去创建一级一级的空文件以及目录(通过Map),再一级一级去拷贝
     */

    /**
     * @param copyOut 被拷贝的文件(目录)
     * @param copyIn  拷贝的文件(目录)
     * @description: 拷贝文件或者目录(包含目录里的文件)
     * @return: boolean
     * @author: soberw
     * @time: 2021/12/15 19:55
     */
    public static boolean copyDir(File copyOut, File copyIn) {
        //如果被拷贝的文件不存在直接退出
        if (!copyOut.exists()) {
            return false;
        }
        //如果目标文件存在但是是文件
        if (copyIn.exists() && copyIn.isFile()) {
            //如果被拷贝对象也是文件
            if (copyOut.isFile()) {
                copyFile(copyOut, copyIn);
                return true;
            } else {
                //否则返回false,因为目录不能往文件中拷贝
                return false;
            }
        } else {
            //如果目标路径不存在,直接创建一个空的以便之后操作
            copyIn.mkdirs();
        }

        //获取路径存入map
        getFilePath(copyOut);
        //取出key放入list
        List<String> list = new ArrayList<>(map.keySet());
        for (String s : list) {
//            System.out.println(s);
            //截取路径头尾,只保留子目录
            String start = s.replace(copyOut.getAbsolutePath(), "");
            String end = start.replace(map.get(s), "");
            //将子目录拼接在目标路径后面
            String path = copyIn.getAbsolutePath() + end;
            File file = new File(path);
            //创建子目录
            if (!file.exists()) {
                file.mkdirs();
            }
            //最后在拼接上文件名(map的value)
            String finalPath = path + map.get(s);
//            System.out.println(finalPath);
            //先创建空文件
            try {
                new File(finalPath).createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
            //拷贝到空文件
            copyFile(new File(s), new File(finalPath));
        }
        return true;
    }

    /**
     * @param file 传入的文件
     * @description: 递归读取传入文件的路径(绝对),放入Map
     * @return: void
     * @author: soberw
     * @time: 2021/12/15 20:28
     */
    private static void getFilePath(File file) {
        if (file.exists()) {
            if (file.isFile()) {
                map.put(file.getAbsolutePath(), file.getName());
            } else if (file.isDirectory()) {
                File[] files = file.listFiles();
                for (File f : files) {
                    getFilePath(f);
                }
            }
        }
    }

    /**
     * @param a 待复制文件路径
     * @param b 复制文件路径(不存在则建立)
     * @description: 将一个文件复制给另一个文件,此方法归copyDir调用
     * @return: void
     * @author: soberw
     * @time: 2021/12/15 20:06
     */
    private static void copyFile(File a, File b) {
        //在copyDir()中判断过文件是否存在,所以不在判断
        if (!b.exists()) {
            try {
                b.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        try (InputStream is = new FileInputStream(a); OutputStream os = new FileOutputStream(b)) {
            //实现对文件a的复制拷贝
            is.transferTo(os);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

测试实现,我要将src复制在这里(现在这里没有):

java复制文件到指定目录导致线程冲突 java拷贝目录_后端_03

package day_12_15.copy_dir;

import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author soberw
 * @Classname CopyDir
 * @Description 拷贝目录(包含目录里的文件)
 * @Date 2021-12-15 19:48
 */
public class CopyDirTest {
    public static void main(String[] args) {
        File f1 = new File("C:\\Users\\soberw\\Desktop\\src");
        File f3 = new File("d:\\src");
        System.out.println(CopyDir.copyDir(f1, f3));
    }
}

拷贝成功!

java复制文件到指定目录导致线程冲突 java拷贝目录_子目录_04


这里给大家安利一个组件,他可以很方便的帮我们实现这些comments-io