To use Files.walk to traverse directories, you call the method with a starting Path. It returns a Stream<Path> that lazily populates as you traverse the file tree in a depth-first manner.
The most important best practice when using Files.walk is to use it within a try-with-resources block. This ensures that the underlying resources (the directory stream) are closed properly after the operation completes.
Basic Usage Example
Here is how you can list every file and directory starting from a specific path:
package org.kodejava.nio;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.stream.Stream;
public class WalkExample {
public static void main(String[] args) {
Path startPath = Paths.get(".");
try (Stream<Path> stream = Files.walk(startPath)) {
stream.forEach(System.out::println);
} catch (IOException e) {
e.printStackTrace();
}
}
}
Filtering and Customizing the Traversal
- Limiting Depth: You can provide a
maxDepthargument to control how many levels deep the traversal should go.// Only traverse up to 2 levels deep try (Stream<Path> stream = Files.walk(startPath, 2)) { stream.forEach(System.out::println); } - Filtering for Files only: Use the
filtermethod on the Stream to exclude directories.try (Stream<Path> stream = Files.walk(startPath)) { stream.filter(Files::isRegularFile) .forEach(System.out::println); } - Handling Symbolic Links: By default,
Files.walkdoes not follow symbolic links. You can enable this by passingFileVisitOption.FOLLOW_LINKS.import java.nio.file.FileVisitOption; // ... try (Stream<Path> stream = Files.walk(startPath, FileVisitOption.FOLLOW_LINKS)) { stream.forEach(System.out::println); }
Key Considerations
- IOException: Unlike many Stream operations,
Files.walkcan throw anIOExceptionduring initialization. Also, if an error occurs during iteration (e.g., a permission issue), it will throw anUncheckedIOException. - Memory Efficiency: Because it returns a
Stream, it is memory-efficient for large directory structures as it doesn’t load all paths into memory at once. - Alternatives: If you need more control (like specific logic when entering a directory or handling errors for specific files), consider using
Files.walkFileTreewith aFileVisitor.
