Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java 8: Copy directory recursively?

I see that Java 8 has significantly cleaned up reading the contents of a file into a String:

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

I am wondering if there is something similar (cleaner/less code/more concise) for copying directories recursively. In Java 7 land, it's still something like:

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

Any improvements here in Java 8?

like image 541
smeeb Avatar asked Mar 16 '15 12:03

smeeb


People also ask

How do you recursively copy?

In order to copy the content of a directory recursively, you have to use the “cp” command with the “-R” option and specify the source directory followed by a wildcard character.

How do you copy a folder from one directory to another?

You can move a file or folder from one folder to another by dragging it from its current location and dropping it into the destination folder, just as you would with a file on your desktop. Folder Tree: Right-click the file or folder you want, and from the menu that displays click Move or Copy.


2 Answers

In this way the code looks a bit simpler

import static java.nio.file.StandardCopyOption.*;  public  void copyFolder(Path src, Path dest) throws IOException {     try (Stream<Path> stream = Files.walk(src)) {         stream.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);     } } 
like image 140
Christian Schneider Avatar answered Sep 19 '22 03:09

Christian Schneider


Using Files.walkFileTree:

  • you don't need to worry about closing Streams.
    (some other answers here forget that while using Files.walk)
  • handles IOException elegantly.
    (Some other answers here would become more difficult when adding proper exception handling instead of a simple 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;             }         });     } 

What this does is

  • walk recursively over all files in the directory.
  • When a directory is encountered (preVisitDirectory):
    create the corresponding one in the target directory.
  • When a regular file is encountered (visitFile):
    copy it.

options can be used to tailor the copy to your needs. For example to overwrite existing files in the target directory, use copyFolder(source, target, StandardCopyOption.REPLACE_EXISTING);

like image 33
neXus Avatar answered Sep 22 '22 03:09

neXus