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:
[code lang=”java”] public static Path walkFileTree(Path start,Set<FileVisitOption> options,
int maxDepth,
FileVisitor<? super Path> visitor)
throws IOException
[/code]
and
[code lang=”java”] public static Path walkFileTree(Path start,FileVisitor<? super Path> visitor)
throws IOException
[/code]
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.
[code lang=”java”] 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;
}
}
[/code]
and the complete program to find the “*.txt” files is:
[code lang=”java”] public class DirectoryScanner {public static void main(String[] args) throws IOException {
Path rootPath = Paths.get("D:/nioTestDir");
Files.walkFileTree(rootPath, new TextFileVisitor());
}
}
[/code]
the output:
[shell] Found: D:\nioTestDir\dir1\dir1Test1.txtFound: 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
[/shell]
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.