In Java, we can use the Java 1.7 FileVisitor
or Apache Commons IO FileUtils.copyDirectory
to copy a directory, which includes its sub-directories and files.
This article shows a few of the common ways to copy a directory in Java.
FileVisitor
(Java 7+)FileUtils.copyDirectory
(Apache commons-io)- Custom Copy using Java 7 NIO and Java 8 Stream.
- Custom Copy, legacy IO.
Note
The NIOFiles.copy
does not support copying directory contents, and we need to create a customized method to copy the directory contents.
1. FileVisitor (Java 7)
This example shows how to use FileVisitor to copy directory and its content from /home/tvt/workspace/favtuts/test/
to /home/tvt/workspace/favtuts/test2/
.
$ tree /home/tvt/workspace/favtuts/test
/home/tvt/workspace/favtuts/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
3 directories, 8 files
1.1 This class extends SimpleFileVisitor
to provide defaults and override only necessary methods.
TreeCopyFileVisitor.java
package com.favtuts.io.utils; import java.io.IOException; import java.nio.file.*; import java.nio.file.attribute.BasicFileAttributes; public class TreeCopyFileVisitor extends SimpleFileVisitor<Path> { 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) throws IOException { System.err.format("Unable to copy: %s: %s%n", file, exc); return FileVisitResult.CONTINUE; } }
1.2 This example uses Files.walkFileTree
to walk the file tree.
CopyDirectory1.java
package com.favtuts.io.howto; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; import com.favtuts.io.utils.TreeCopyFileVisitor; public class CopyDirectory { public static void main(String[] args) { String fromDirectory = "/home/tvt/workspace/favtuts/test/"; String toToDirectory = "/home/tvt/workspace/favtuts/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); } }
Output
Create directories : /home/tvt/workspace/favtuts/test2 Copy File from '/home/tvt/workspace/favtuts/test/test-a1.log' to '/home/tvt/workspace/favtuts/test2/test-a1.log' Copy File from '/home/tvt/workspace/favtuts/test/test-a2.log' to '/home/tvt/workspace/favtuts/test2/test-a2.log' Create directories : /home/tvt/workspace/favtuts/test2/test-b Copy File from '/home/tvt/workspace/favtuts/test/test-b/test-b2.txt' to '/home/tvt/workspace/favtuts/test2/test-b/test-b2.txt' Create directories : /home/tvt/workspace/favtuts/test2/test-b/test-d Copy File from '/home/tvt/workspace/favtuts/test/test-b/test-d/test-d1.log' to '/home/tvt/workspace/favtuts/test2/test-b/test-d/test-d1.log' Copy File from '/home/tvt/workspace/favtuts/test/test-b/test-d/test-d2.log' to '/home/tvt/workspace/favtuts/test2/test-b/test-d/test-d2.log' Create directories : /home/tvt/workspace/favtuts/test2/test-b/test-c Copy File from '/home/tvt/workspace/favtuts/test/test-b/test-c/test-c2.log' to '/home/tvt/workspace/favtuts/test2/test-b/test-c/test-c2.log' Copy File from '/home/tvt/workspace/favtuts/test/test-b/test-c/test-c1.log' to '/home/tvt/workspace/favtuts/test2/test-b/test-c/test-c1.log' Copy File from '/home/tvt/workspace/favtuts/test/test-b/test-b1.txt' to '/home/tvt/workspace/favtuts/test2/test-b/test-b1.txt' Done
Check the new directory.
$ tree /home/tvt/workspace/favtuts/test2
/home/tvt/workspace/favtuts/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
3 directories, 8 files
Note
The official Java Copy example copies everything, including the file attribute. However, it is harder to read; this example simplifies the method to only copy files and directories and excludes the attributes.
2. FileUtils.copyDirectory (Apache commons-io)
This example uses FileUtils.copyDirectory
to copy a directory and its content, a friendly, and straightforward API.
pom.xml
<dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.7</version> </dependency>
CopyDirectory2.java
package com.favtuts.io.howto; import java.io.File; import java.io.IOException; import com.favtuts.io.utils.TreeCopyFileVisitor; import org.apache.commons.io.FileUtils; public class CopyDirectory { public static void main(String[] args) { String fromDirectory = "/home/tvt/workspace/favtuts/test/"; String toToDirectory = "/home/tvt/workspace/favtuts/test2/"; try { copyFileCommonIO(fromDirectory, toToDirectory); } catch (IOException e) { e.printStackTrace(); } System.out.println("Done"); } 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 and Stream.
This example uses Java 8 Files.list
to simulate a file walker and Java 7 NIO Files
to check, create, and copy the directory and its content.
CopyDirectory3.java
package com.favtuts.io.howto; import java.io.File; 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; import com.favtuts.io.utils.TreeCopyFileVisitor; import org.apache.commons.io.FileUtils; public class CopyDirectory { public static void main(String[] args) { String fromDirectory = "/home/tvt/workspace/favtuts/test/"; String toToDirectory = "/home/tvt/workspace/favtuts/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<Path> 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. Legacy IO
This example is similar to method 3. Instead, it sticks with the legacy IO java.io.*
, just for reference.
CopyDirectory4.java
package com.favtuts.io.howto; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.stream.Stream; public class CopyDirectory { public static void main(String[] args) { String fromDirectory = "/home/tvt/workspace/favtuts/test/"; String toToDirectory = "/home/tvt/workspace/favtuts/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(); } } } } }
Note
Java, after 20+ years, there is still no official API to copy a directory, how hard to create a
Files.copyDirectory()
?
Download Source Code
$ git clone https://github.com/favtuts/java-core-tutorials-examples
$ cd java-io/file – howto