Java 8:递归复制目录?

sme*_*eeb 26 recursion file-copying java-8

我看到Java 8已经大大清理了将文件内容读入String:

String contents = new String(Files.readAllBytes(Paths.get(new URI(someUrl))));
Run Code Online (Sandbox Code Playgroud)

我想知道是否有类似的东西(更干净/更少的代码/更简洁)递归复制目录.在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();
    }
}
Run Code Online (Sandbox Code Playgroud)

Java 8中的任何改进?

Chr*_*der 16

通过这种方式,代码看起来更简单一些

import static java.nio.file.StandardCopyOption.*;

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 它确实复制子文件夹及其内容。 (2认同)

neX*_*Xus 16

使用Files.walkFileTree

  • 您无需担心关闭 Streams。
    (这里的其他一些答案在使用时忘记了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 {
                Files.createDirectories(target.resolve(source.relativize(dir)));
                return FileVisitResult.CONTINUE;
            }

            @Override
            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
                    throws IOException {
                Files.copy(file, target.resolve(source.relativize(file)), options);
                return FileVisitResult.CONTINUE;
            }
        });
    }
Run Code Online (Sandbox Code Playgroud)

这是做什么的

  • 递归遍历目录中的所有文件。
  • 遇到目录时(preVisitDirectory):
    在目标目录中创建对应的目录。
  • 当遇到常规文件 ( visitFile) 时:
    复制它。

options可用于根据您的需要定制副本。例如要覆盖目标目录中的现有文件,请使用copyFolder(source, target, StandardCopyOption.REPLACE_EXISTING);

  • 如果您想跟踪符号链接,可以替换 [`Files.walkFileTree(source, guest)`](https://docs.oracle.com/javase/8/docs/api/java/nio/file/Files. html#walkFileTree-java.nio.file.Path-java.nio.file.FileVisitor-) 与 [`Files.walkFileTree(source, EnumSet.of(FOLLOW_LINKS), Integer.MAX_VALUE, guest)`](https:// docs.oracle.com/javase/8/docs/api/java/nio/file/Files.html#walkFileTree-java.nio.file.Path-java.util.Set-int-java.nio.file.FileVisitor- ) (2认同)

Moh*_*war 14

以下代码如何?

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();
                }
            });
        }
    }
Run Code Online (Sandbox Code Playgroud)

  • 使用Path API可以更优雅地确定目标路径:`Path target = targetDir.resolve(sourceDir.relativize(path))` (4认同)
  • 请不要捕获异常和 printStackTrace。将 IOException 包装到 UncheckedIOException 中是合适的。 (2认同)

Sas*_*sov 7

此版本使用Java 8建议的Files.walkPath参数。

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();
    }
}
Run Code Online (Sandbox Code Playgroud)


pwi*_*ipo 0

我的版本:

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();
    }

    File[] files = src.listFiles();
    if(files==null || files.length==0)
        return;

    for(File file: files){
        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();
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)