A directory is an organizational file system structure that contains files and other directories. Java provides a few ways to traverse a directory, depending on which version you are using, including:
- Using the listFiles() method of the File class
- Using a DirectoryStream in Java 7 and onwards
- Using the static Files.list() method in Java 8 and onwards
- Using the walk() method in Java 8 and onwards
This programming tutorial will demonstrate how to utilize each of the above techniques to navigate a directory structure in Java.
SEE: Top Java IDEs
The File listFiles() method in Java
listFiles() is an instance method of the java.io.File class. To use it, all developers need to do is instantiate a new File object by providing a path to the constructor and and then invoke listFiles() on it. listFiles() returns an array of File objects that programmers can then iterate over to obtain more information about individual files and/or perform operations on them. Here is a basic example that lists all of the files and directories in the Windows “C:\My Documents” folder:
package com.developer; import java.io.File; public class ListFilesExample { public static void main(String[] args) { // Store the name of files and directories // in an array of Files. // Don't forget to escape the backslash character! File[] files = new File("C:\\My Documents").listFiles(); // Traverse through the files array for (File file : files) { // If a subdirectory is found, // print the name of the subdirectory if (file.isDirectory()) { System.out.println("Directory: " + file.getName()); } else { // Print the file name System.out.println("File: " + file.getName()); } } } }
Here is a partial listing of the directories and files found:
Directory: AAMS Directory: Addictive Drums Directory: Angular Directory: angular-starter Directory: Any Video Converter Directory: articles File: Avatar - House Of Eternal Hunt - transposed.tg File: Avatar - House Of Eternal Hunt.tg File: Avatar - Legend Of The King.tg Directory: bgfx
Recursive directory traversal in Java
Since we can test for directories, we can move our for loop into a separate method that we can invoke recursively to list the files of subdirectories as well as the one provided to our method, as shown in the follow Java code example:
package com.developer; import java.io.File; public class RecursiveListFilesExample { public static void main(String[] args) { listFilesInDirectory(new File("C:\\My Documents")); } private static void listFilesInDirectory(File dirPath) { File filesList[] = dirPath.listFiles(); // Traverse through the files array for (File file : filesList) { // If a sub directory is found, // print the name of the sub directory if (file.isDirectory()) { System.out.println("Directory: " + file.getName()); listFilesInDirectory(file); } else { // Print the file name present in given path System.out.println("File: " + file.getName()); } } } }
We can see in the program output that it is now listing the files of subdirectories as well:
Directory: AAMS File: AAMS V3 Manual.pdf File: AAMS V4 Setup.exe File: AAMS.xml File: Licence.txt File: Version.txt Directory: Addictive Drums Directory: Settings File: MidifileDatabaseCache.dat File: Recent.dat
SEE: Top online Java courses to learn Java
Using DirectoryStream to loop through files with Java
Java 7 introduced an alternative to listFiles() called DirectoryStream. It works well with the for-each construct, allowing us to iterate over the contents of the directory instead of reading everything at once.
The example code below shows how to use Java’s DirectoryStream in a method to list the files of a directory:
public Set<String> listFilesUsingDirectoryStream(String dir) throws IOException { Set<String> fileSet = new HashSet<>(); try (DirectoryStream<Path> stream = Files.newDirectoryStream( Paths.get(dir))) { for (Path path : stream) { if (!Files.isDirectory(path)) { fileSet.add(path.getFileName() .toString()); } } } return fileSet; }
Above, we let Java handle the closing of the DirectoryStream resource through the try-with-resources construct. We can employ the static Files.isDirectory(path) method to filter out directories and return a Set of files in the folder.
Using the static Files.list() Method
Java 8 introduced a new list() method in java.nio.file.Files. The list method returns a lazily populated Stream of entries in the directory. As such, it is more efficient for processing large folders. Here is a method that returns a Set of file names:
public Set<String> listFilesUsingFilesList(String dir) throws IOException { try (Stream<Path> stream = Files.list(Paths.get(dir))) { return stream .filter(file -> !Files.isDirectory(file)) .map(Path::getFileName) .map(Path::toString) .collect(Collectors.toSet()); } }
Although the above code might look similar to listFiles(), it is different in how developers obtain each file’s path.
Again, we created the stream using the try-with-resources construct to ensure that the directory resource is closed after reading the stream.
How to walk over directory contents in Java
The walk() method returns a Stream by walking the file tree beginning with a given starting file/directory in a depth-first manner (meaning that it starts with the file/directory at the greatest depth). The following program prints the full file paths for the full file tree under “C:\My Documents”:
import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.stream.Stream; class FilesWalkExample { public static void main(String[] args) throws IOException { // Create a try-catch block and // provide the directory path of local machine try (Stream<Path> filepath = Files.walk(Paths.get("C:\\My Documents"))) { // Print the entire path of directories and files filepath.forEach(System.out::println); } // Throw an if directory doesn't exists catch (IOException e) { throw new IOException("Directory not found!"); } } }
The first few lines of output confirm that file traversal started the greatest depth:
I:\My Documents\Angular\my-app\node_modules\selenium-webdriver\ lib\test\data\proxy I:\My Documents\Angular\my-app\node_ modules\selenium-webdriver\ lib\test\data\proxy\page1.html I:\My Documents\Angular\my-app\node_ modules\selenium-webdriver\ lib\test\data\proxy\page2.html I:\My Documents\Angular\my-app\node_ modules\selenium-webdriver\ lib\test\data\proxy\page3.html I:\My Documents\Angular\my-app\node_ modules\selenium-webdriver\ lib\test\data\readOnlyPage. html I:\My Documents\Angular\my-app\node_ modules\selenium-webdriver\ lib\test\data\rectangles.html I:\My Documents\Angular\my-app\node_ modules\selenium-webdriver\ lib\test\data\Redirect.aspx I:\My Documents\Angular\my-app\node_ modules\selenium-webdriver\ lib\test\data\Redirect.aspx.cs I:\My Documents\Angular\my-app\node_ modules\selenium-webdriver\ lib\test\data\resultPage.html
We could include directories as well by removing the Files::isRegularFile filter condition.
Final thoughts on Directory Navigation in Java
Java provides a few ways to traverse a directory, depending on which version you are using. Although we covered the main ones, there are other ways to navigate directories in Java, especially since the Stream API was introduced in Java 8.
SEE: Maven build automation tool review