At times we might want to search for some file in a directory traversing recursively into other directories with in that directory, I know getting the recursive program right at the first time is always a challenge. Or we might want to list all the contents of a directory. For all these operations the NIO2 enhancements in Java 7 provides an API to recursively traverse through a path and another interface which can be extended to provide hooks for performing certain operations when a file is encountered or a directory is encountered.
also read:
The method used is: Files.walkFileTree. There are 2 overloaded versions of this method:
public static Path walkFileTree(Path start, Set<FileVisitOption> options, int maxDepth, FileVisitor<? super Path> visitor) throws IOException
and
public static Path walkFileTree(Path start, FileVisitor<? super Path> visitor) throws IOException
Currently FileVisitOption enum provides an option to specify whether or not to follow the symbolic links. The maxDepth restricts the number of levels the walkFileTree method would traverse into for a given directory.
The FileVisitor interface is the major player in this operation. It has the following methods:
- postVisitDirectory(T dir, IOException exc): Invoked for a directory after entries in the directory, and all of their descendants, have been visited.
- preVisitDirectory(T dir, BasicFileAttributes attrs): Invoked for a directory before entries in the directory are visited.
- visitFile(T file, BasicFileAttributes attrs): Invoked for a file in a directory.
- visitFileFailed(T file, IOException exc): Invoked for a file that could not be visited.
Each of these methods return a FileVisitResult, which is another enum with the following constants:
- CONTINUE: Continue.
- SKIP_SIBLINGS: Continue without visiting the siblings of this file or directory.
- SKIP_SUBTREE: Continue without visiting the entries in this directory.
- TERMINATE: Terminate.
I have created a test dir with the following contents:
and the dir1 contains:
Lets write a program to list all the text files in the folder: “D:\nioTestDir”. First we need to implement the FileVisitor interface. We can make use of SimpleFileVisitor class which implements the FileVisitor interface and provides default operations for all the methods.
class TextFileVisitor extends SimpleFileVisitor<Path>{ PathMatcher matcher; public TextFileVisitor(){ matcher = FileSystems.getDefault().getPathMatcher("glob:*.txt"); } @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { Path fileName = file.getFileName(); if ( matcher.matches(fileName)){ System.out.println("Found: "+ file); } //Continue to search for other txt files return FileVisitResult.CONTINUE; } }
and the complete program to find the “*.txt” files is:
public class DirectoryScanner { public static void main(String[] args) throws IOException { Path rootPath = Paths.get("D:/nioTestDir"); Files.walkFileTree(rootPath, new TextFileVisitor()); } }
the output:
Found: D:\nioTestDir\dir1\dir1Test1.txt Found: D:\nioTestDir\dir1\dir1Test2.txt Found: D:\nioTestDir\dir1\dir1Test3.txt Found: D:\nioTestDir\test1.txt Found: D:\nioTestDir\test2.txt Found: D:\nioTestDir\test3.txt
This new API has made it really easy to traverse any given path to get the contents of the file/directory represented by the path. The above example was a simple way to list all the “.txt” files in the given path.