Рубрики
Без рубрики

Как скопировать каталог на Java

В Java мы можем использовать `FileVisitor` для копирования каталога, который включает в себя его подкаталоги и файлы.

Автор оригинала: mkyong.

В Java мы можем использовать Java 1.7 FileVisitor или Apache Commons IO FileUtils.copydirectory для копирования каталога, который включает в себя его подкаталоги и файлы.

В этой статье показано несколько распространенных способов копирования каталога на Java.

  1. Файловый посетитель ( Java 7+)
  2. Каталог файлов.copydirectory (Apache commons-io)
  3. Пользовательское копирование с использованием Java 7 NIO и Java 8 Stream.
  4. Пользовательская копия, устаревший ввод-вывод.

Примечание NIO Files.copy не поддерживает копирование содержимого каталога, и нам нужно создать индивидуальный метод для копирования содержимого каталога.

1. Просмотрщик файлов (Java 7)

В этом примере показано, как использовать FileVisitor для копирования каталога и его содержимого из /home/mkyong/test/| в |home/mkyong/test 2/ .

$ tree /home/mkyong/test
test
├── test-a1.log
├── test-a2.log
└── test-b
    ├── test-b1.txt
    ├── test-b2.txt
    ├── test-c
    │   ├── test-c1.log
    │   └── test-c2.log
    └── test-d
        ├── test-d1.log
        └── test-d2.log

1.1 Этот класс расширяет SimpleFileVisitor для предоставления значений по умолчанию и переопределения только необходимых методов.

package com.mkyong.io.utils;

import java.io.IOException;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;

public class TreeCopyFileVisitor extends SimpleFileVisitor {

    private Path source;
    private final Path target;

    public TreeCopyFileVisitor(String source, String target) {
        this.source = Paths.get(source);
        this.target = Paths.get(target);
    }

    @Override
    public FileVisitResult preVisitDirectory(Path dir,
        BasicFileAttributes attrs) throws IOException {

        Path resolve = target.resolve(source.relativize(dir));
        if (Files.notExists(resolve)) {
            Files.createDirectories(resolve);
            System.out.println("Create directories : " + resolve);
        }
        return FileVisitResult.CONTINUE;

    }

    @Override
    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
        throws IOException {

        Path resolve = target.resolve(source.relativize(file));
        Files.copy(file, resolve, StandardCopyOption.REPLACE_EXISTING);
        System.out.println(
                String.format("Copy File from \t'%s' to \t'%s'", file, resolve)
        );

        return FileVisitResult.CONTINUE;

    }

    @Override
    public FileVisitResult visitFileFailed(Path file, IOException exc) {
        System.err.format("Unable to copy: %s: %s%n", file, exc);
        return FileVisitResult.CONTINUE;
    }

}

1.2 В этом примере используется Files.walkFileTree для обхода дерева файлов.

package com.mkyong.io.howto;

import com.mkyong.io.utils.TreeCopyFileVisitor;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;

public class CopyDirectory1 {

    public static void main(String[] args) {

        String fromDirectory = "/home/mkyong/test/";
        String toToDirectory = "/home/mkyong/test2/";

        try {

            copyDirectoryFileVisitor(fromDirectory, toToDirectory);

        } catch (IOException e) {
            e.printStackTrace();
        }

        System.out.println("Done");

    }

    public static void copyDirectoryFileVisitor(String source, String target)
        throws IOException {

        TreeCopyFileVisitor fileVisitor = new TreeCopyFileVisitor(source, target);
        Files.walkFileTree(Paths.get(source), fileVisitor);

    }

}

Выход

Create directories : /home/mkyong/test2
Copy File from 	'/home/mkyong/test/test-a2.log' to 	'/home/mkyong/test2/test-a2.log'
Copy File from 	'/home/mkyong/test/test-a1.log' to 	'/home/mkyong/test2/test-a1.log'
Create directories : /home/mkyong/test2/test-b
Copy File from 	'/home/mkyong/test/test-b/test-b1.txt' to 	'/home/mkyong/test2/test-b/test-b1.txt'
Create directories : /home/mkyong/test2/test-b/test-c
Copy File from 	'/home/mkyong/test/test-b/test-c/test-c2.log' to 	'/home/mkyong/test2/test-b/test-c/test-c2.log'
Copy File from 	'/home/mkyong/test/test-b/test-c/test-c1.log' to 	'/home/mkyong/test2/test-b/test-c/test-c1.log'
Copy File from 	'/home/mkyong/test/test-b/test-b2.txt' to 	'/home/mkyong/test2/test-b/test-b2.txt'
Create directories : /home/mkyong/test2/test-b/test-d
Copy File from 	'/home/mkyong/test/test-b/test-d/test-d2.log' to 	'/home/mkyong/test2/test-b/test-d/test-d2.log'
Copy File from 	'/home/mkyong/test/test-b/test-d/test-d1.log' to 	'/home/mkyong/test2/test-b/test-d/test-d1.log'
Done

Проверьте новый каталог.

$ tree /home/mkyong/test2
test2
├── test-a1.log
├── test-a2.log
└── test-b
    ├── test-b1.txt
    ├── test-b2.txt
    ├── test-c
    │   ├── test-c1.log
    │   └── test-c2.log
    └── test-d
        ├── test-d1.log
        └── test-d2.log

Примечание Официальный Пример копирования Java копирует все, включая атрибут файла. Однако это сложнее для чтения; этот пример упрощает метод только для копирования файлов и каталогов и исключает атрибуты.

2. Каталог файлов.copydirectory (Apache commons-io)

В этом примере используется FileUtils.copydirectory для копирования каталога и его содержимого используется удобный и простой API.

  
      commons-io
      commons-io
      2.7
  
import org.apache.commons.io.FileUtils;

  //...

  public static void copyFileCommonIO(String from, String to)
      throws IOException {

      File fromDir = new File(from);
      File toDir = new File(to);

      FileUtils.copyDirectory(fromDir, toDir);

  }

3. Java NIO и поток.

В этом примере используются файлы Java 8 .список для имитации перемещения файлов и Java 7 NIO Файлы для проверки, создания и копирования каталога и его содержимого.

package com.mkyong.io.howto;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.stream.Stream;

public class CopyDirectory3 {

    public static void main(String[] args) {

        String fromDirectory = "/home/mkyong/test/";
        String toToDirectory = "/home/mkyong/test2/";

        try {

            copyDirectoryJavaNIO(Paths.get(fromDirectory),
                Paths.get(toToDirectory));

        } catch (IOException e) {
            e.printStackTrace();
        }

        System.out.println("Done");

    }

    public static void copyDirectoryJavaNIO(Path source, Path target)
            throws IOException {

        // is this a directory?
        if (Files.isDirectory(source)) {

            //if target directory exist?
            if (Files.notExists(target)) {
                // create it
                Files.createDirectories(target);
                System.out.println("Directory created : " + target);
            }

            // list all files or folders from the source, Java 1.8, returns a stream
            // doc said need try-with-resources, auto-close stream
            try (Stream paths = Files.list(source)) {

                // recursive loop
                paths.forEach(p ->
                        copyDirectoryJavaNIOWrapper(
                          p, target.resolve(source.relativize(p)))
                );

            }

        } else {
            // if file exists, replace it
            Files.copy(source, target, StandardCopyOption.REPLACE_EXISTING);
            System.out.println(
                    String.format("Copy File from \t'%s' to \t'%s'", source, target)
            );
        }
    }

    // extract method to handle exception in lambda
    public static void copyDirectoryJavaNIOWrapper(Path source, Path target) {

        try {
            copyDirectoryJavaNIO(source, target);
        } catch (IOException e) {
            System.err.println("IO errors : " + e.getMessage());
        }

    }

}

4. Унаследованный IO

Этот пример аналогичен методу 3. Вместо этого он придерживается устаревшего ввода-вывода java.io . * , просто для справки.

package com.mkyong.io.howto;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.stream.Stream;

public class CopyDirectory4 {

    public static void main(String[] args) {

        String fromDirectory = "/home/mkyong/test/";
        String toToDirectory = "/home/mkyong/test2/";

        try {

            copyDirectoryLegacyIO(
                new File(fromDirectory),
                new File(toToDirectory));

        } catch (IOException e) {
            e.printStackTrace();
        }

        System.out.println("Done");

    }

    public static void copyDirectoryLegacyIO(File source, File target)
        throws IOException {

        if (source.isDirectory()) {

            //if directory not exists, create it
            if (!target.exists()) {
                if (target.mkdir()) {
                    System.out.println("Directory copied from "
                            + source + "  to " + target);
                } else {
                    System.err.println("Unable to create directory : " + target);
                }
            }

            // list all the directory contents, file walker
            String[] files = source.list();
            if (files == null) {
                return;
            }

            for (String file : files) {
                //construct the src and dest file structure
                File srcFile = new File(source, file);
                File destFile = new File(target, file);
                //recursive copy
                copyDirectoryLegacyIO(srcFile, destFile);
            }

        } else {

            //if file, then copy it
            //Use bytes stream to support all file types
            InputStream in = null;
            OutputStream out = null;

            try {

                in = new FileInputStream(source);
                out = new FileOutputStream(target);

                byte[] buffer = new byte[1024];

                int length;
                //copy the file content in bytes
                while ((length = in.read(buffer)) > 0) {
                    out.write(buffer, 0, length);
                }

                System.out.println("File copied from " + source + " to " + target);

            } catch (IOException e) {

                System.err.println("IO errors : " + e.getMessage());

            } finally {
                if (in != null) {
                    in.close();
                }

                if (out != null) {
                    out.close();
                }
            }
        }

    }

}

Примечание Java, после 20+лет , до сих пор нет официального API для копирования каталога, как сложно создать Каталог файлов.копировать() ?

Скачать Исходный Код

$клон git $клон git

$cd java-ввод-вывод

Рекомендации

Оригинал: “https://mkyong.com/java/how-to-copy-directory-in-java/”