递归地将目录和文件复制到目标

Recursively copy directories and files into destination

我们在 Java 中有以下任务:

Given a list of directories and files followed by the destination copy all these directories(recursively) and files into the destination. Note: all the subdirectories and files inside the given directories must be kept in the same nested structure in destination folder.

We take array of files as an input as well as the destination folder. The output must produce something like this:

Started: resources\docs\books...
Started: resources\docs\books\american...
Started: resources\docs\books\american\London...
Started: resources\docs\books\american\London\BEFORE ADAM.txt...
Finished FILE: resources\docs\books\american\London\BEFORE ADAM.txt
Total 229KB were copied!
Started: resources\docs\books\american\London\THE IRON HEEL.txt...
Finished FILE: resources\docs\books\american\London\THE IRON HEEL.txt
Total 528KB were copied!
Started: resources\docs\books\american\London\The People of the Abyss.txt...
Finished FILE: resources\docs\books\american\London\The People of the Abyss.txt
Total 370KB were copied!
Finished FOLDER: resources\docs\books\american\London
Finished FOLDER: resources\docs\books\american

有没有人有什么想法?

您可以通过实现 FileVisitor 接口轻松实现这一点。这是一个代码示例,只是为了向您展示它是如何工作的。它应该按照你的要求去做。

编辑:更新了自定义尺寸处理

public class FileCopier implements FileVisitor<Path> {

    private final Path sourcePath;
    private final Path targetPath;

    private HashMap<String, Long> mapSize;

    public FileCopier(Path sourcePath, Path targetPath) throws IOException {
        //Check whether the destination directory exists or not
        if (!Files.exists(targetPath)) {
            Files.createDirectories(targetPath);
        }

        this.sourcePath = sourcePath.toRealPath();
        this.targetPath = targetPath.toRealPath();
        this.mapSize = new HashMap<>();
    }

    @Override
    public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
        //Copying the directory first and then its content (directory copy does not copy its content)

        //Retrieving the last bit of the path starting from the source location
        Path lastBitPath = sourcePath.relativize(dir.toAbsolutePath().normalize());

        //Adding the last bit to the target path
        Path targetCopyPath = targetPath.resolve(lastBitPath).toAbsolutePath().normalize();

        if (!Files.exists(targetCopyPath)) {
            Files.copy(dir, targetCopyPath, StandardCopyOption.COPY_ATTRIBUTES);
        }

        //Defining 0 bytes for the new visited directory
        mapSize.put(targetCopyPath.toString(), 0L);
        System.out.println("Started: " + targetCopyPath);
        return FileVisitResult.CONTINUE;
    }

    @Override
    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
        Path targetCopyPath = targetPath.resolve(sourcePath.relativize(file.toAbsolutePath().normalize())).toAbsolutePath().normalize();
        Files.copy(file, targetCopyPath, StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.COPY_ATTRIBUTES);
        
        //Adding the current copied file's bytes to the corresponding folder
        mapSize.put(targetCopyPath.getParent().toString(), mapSize.get(targetCopyPath.getParent().toString()) + Files.size(file));
        System.out.println("Finished FILE: " + targetCopyPath);
        return FileVisitResult.CONTINUE;
    }

    @Override
    public FileVisitResult visitFileFailed(Path file, IOException exc) {
        return FileVisitResult.TERMINATE;
    }

    @Override
    public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
        //Retrieving the last bit of the path starting from the source location
        Path lastBitPath = sourcePath.relativize(dir.toAbsolutePath().normalize());

        //Adding the last bit to the target path
        Path targetCopyPath = targetPath.resolve(lastBitPath).toAbsolutePath().normalize();

        //Showing the number of bytes copied within the copied directory
        System.out.println("Total " + this.mapSize.get(targetCopyPath.toString()) + " bytes were copied into " + targetCopyPath);
        return FileVisitResult.CONTINUE;
    }

    public static void main(String[] args) throws IOException {
        Path sourcePath = Paths.get("./test");
        Path targetPath = Paths.get("./subtest");
        FileCopier fc = new FileCopier(sourcePath, targetPath);
        Files.walkFileTree(sourcePath, fc);
    }
}