web-dev-qa-db-ja.com

Java 8:ディレクトリを再帰的にコピーしますか?

Java 8は、ファイルの内容を文字列に読み込むことを大幅にクリーンアップしました:

String contents = new String(Files.readAllBytes(Paths.get(new URI(someUrl))));

ディレクトリを再帰的にコピーするための同様の(よりクリーンでより少ないコード/より簡潔な)ものがあるかどうか疑問に思っています。 Java 7ランドでは、それはまだ次のようなものです:

public void copyFolder(File src, File dest) throws IOException{
    if(src.isDirectory()){
        if(!dest.exists()){
            dest.mkdir();
        }

        String files[] = src.list();

        for (String file : files) {
            File srcFile = new File(src, file);
            File destFile = new File(dest, file);

            copyFolder(srcFile,destFile);
        }

    } else {
        InputStream in = new FileInputStream(src);
        OutputStream out = new FileOutputStream(dest); 

        byte[] buffer = new byte[1024];

        int length;
        while ((length = in.read(buffer)) > 0){
            out.write(buffer, 0, length);
        }

        in.close();
        out.close();
    }
}

Java 8?

30
smeeb

このように、コードは少し単純に見えます

public  void copyFolder(Path src, Path dest) throws IOException {
    Files.walk(src)
        .forEach(source -> copy(source, dest.resolve(src.relativize(source))));
}

private void copy(Path source, Path dest) {
    try {
        Files.copy(source, dest, REPLACE_EXISTING);
    } catch (Exception e) {
        throw new RuntimeException(e.getMessage(), e);
    }
}
16

次のコードはどうですか

public void copyFolder(File src, File dest) throws IOException {
        try (Stream<Path> stream = Files.walk(src.toPath())) {
            stream.forEachOrdered(sourcePath -> {

                try {
                    Files.copy(
                            /*Source Path*/
                            sourcePath,
                            /*Destination Path */
                            src.toPath().resolve(dest.toPath().relativize(sourcePath)));
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            });
        }
    }
13
Mohit Kanwar

このバージョンでは、=Files.walkおよびPathパラメータをJava 8が示唆するように)使用します。

public static void copyFolder(Path src, Path dest) {
    try {
        Files.walk( src ).forEach( s -> {
            try {
                Path d = dest.resolve( src.relativize(s) );
                if( Files.isDirectory( s ) ) {
                    if( !Files.exists( d ) )
                        Files.createDirectory( d );
                    return;
                }
                Files.copy( s, d );// use flag to override existing
            } catch( Exception e ) {
                e.printStackTrace();
            }
        });
    } catch( Exception ex ) {
        ex.printStackTrace();
    }
}
6
Sasha Firsov

そしてもう1つのバージョン:

static void copyFolder(File src, File dest){
    // checks
    if(src==null || dest==null)
        return;
    if(!src.isDirectory())
        return;
    if(dest.exists()){
        if(!dest.isDirectory()){
            //System.out.println("destination not a folder " + dest);
            return;
        }
    } else {
        dest.mkdir();
    }

    if(src.listFiles()==null || src.listFiles().length==0)
        return;

    String strAbsPathSrc = src.getAbsolutePath();
    String strAbsPathDest = dest.getAbsolutePath();

    try {
        Files.walkFileTree(src.toPath(), new SimpleFileVisitor<Path>() {
            @Override
            public FileVisitResult visitFile(Path file,
                    BasicFileAttributes attrs) throws IOException {
                File dstFile = new File(strAbsPathDest + file.toAbsolutePath().toString().substring(strAbsPathSrc.length()));
                if(dstFile.exists())
                    return FileVisitResult.CONTINUE;

                if(!dstFile.getParentFile().exists())
                    dstFile.getParentFile().mkdirs();

                //System.out.println(file + " " + dstFile.getAbsolutePath());
                Files.copy(file, dstFile.toPath());

                return FileVisitResult.CONTINUE;
            }
        });

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

    return;
}

そのコードはJava8 Files.walkFileTree関数を使用します。

1
pwipo

私のバージョン:

static private void copyFolder(File src, File dest) {
    // checks
    if(src==null || dest==null)
        return;
    if(!src.isDirectory())
        return;
    if(dest.exists()){
        if(!dest.isDirectory()){
            //System.out.println("destination not a folder " + dest);
            return;
        }
    } else {
        dest.mkdir();
    }

    if(src.listFiles()==null || src.listFiles().length==0)
        return;

    for(File file: src.listFiles()){
        File fileDest = new File(dest, file.getName());
        //System.out.println(fileDest.getAbsolutePath());
        if(file.isDirectory()){
            copyFolder(file, fileDest);
        }else{
            if(fileDest.exists())
                continue;

            try {
                Files.copy(file.toPath(), fileDest.toPath());
            } catch (IOException e) {
                //e.printStackTrace();
            }
        }
    }
}
1
pwipo

_Files.walkFileTree_の使用:

  • ストリームを閉じることについて心配する必要はありません。
    (ここで他のいくつかの回答は、_Files.walk_を使用している間はそれを忘れます)
  • IOExceptionをエレガントに扱います。
    (ここでの他のいくつかの答えは、単純なprintStackTraceの代わりに適切な例外処理を追加すると、より困難になります)
_    public void copyFolder(Path source, Path target, CopyOption... options)
            throws IOException {
        Files.walkFileTree(source, new SimpleFileVisitor<Path>() {

            @Override
            public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs)
                    throws IOException {
                createDirectories(target.resolve(source.relativize(dir)));
                return FileVisitResult.CONTINUE;
            }

            @Override
            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
                    throws IOException {
                copy(source, target.resolve(source.relativize(file)), options);
                return FileVisitResult.CONTINUE;
            }
        });
    }
_

これは何ですか

  • ディレクトリ内のすべてのファイルを再帰的にウォークします。
  • ディレクトリが見つかると(preVisitDirectory):
    ターゲットディレクトリに対応するものを作成します。
  • 通常のファイルが検出された場合(visitFile):
    それをコピーします。

options を使用して、ニーズに合わせてコピーを調整できます。たとえば、ターゲットディレクトリ内の既存のファイルを上書きするには、copyFolder(source, target, StandardCopyOption.REPLACE_EXISTING);を使用します

0
neXus