Traversing a file tree in NIO.2

Have you downloaded JDK7 and played with NIO.2 yet? NIO.2 offers many new I/O features, particularly in the area of files and file system APIs. (To those of you who think, I can't use JDK7 because I am on a Mac: So am I. What I did was to download VirtualBox for my Mac (it's free). This allows you to set up a virtual environment on your machine. You can then download OpenSolaris, Ubuntu, or even Windows (but OpenSolaris and Ubuntu are free).

I wrote a simple example which you can use to find a file on your file system. (Think of a very simplified version of the Unix find.) The new java.nio.file.Files class provides a factory method, walkFileTree, you can use to traverse a tree of directories and files. When you invoke this method, you specify the root and how many levels deep you want to go. You can also set an attribute to indicate that it should follow links.

The meat of the work occurs in a class you create that implements the java.nio.file.FileVisitor interface. This interface has hooks for before, during, and after a file is "visited", as well as for when failure occurs. In my simple Find example, when the file is visited, the file name is compared to the user-specified name. If it matches, the full path is printed to stdout.

You create an instance of this class and pass it to the walkFileTree method. For each file or directory in the tree, the instance is invoked. You will notice that in this example, CONTINUE is returned in each of the FileVisitor methods. You can also return SKIP_SUBTREE or SKIP_SIBLINGS to terminate progress when necessary.

That's it.

If you download the NIO.2 JDK7 binaries, you will find other NIO.2 examples. Three of them also use the walkFileTree method: Chmod.java, Copy.java and WatchDir.java.

To call Find: java Find path file.

Here is the code for Find.java:

/\*\*
 \* Sample code that finds files.  Similar to the find(1) program, but simplified.
 \*/

public class Find {
    /\*\*
     \* A {@code FileVisitor} that finds a file.
     \*/
    static class Finder implements FileVisitor {
        private final Path findFile;

        Finder(Path findFile) {
            this.findFile = findFile;
        }

        void find(Path file) {
            if (file.getName().equals(findFile)) {
                System.out.format("%s%n", findFile);
            }
        }

        @Override
        public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
            find(file);
            return CONTINUE;
        }

        @Override
        public FileVisitResult postVisitDirectory(Path dir, IOException exc) {
            return CONTINUE;
        }

        @Override
        public FileVisitResult visitFileFailed(Path file, IOException exc) {
            return CONTINUE;
        }

        @Override
        public FileVisitResult preVisitDirectory(Path dir) {
            find(dir);
            return CONTINUE;
        }

        @Override
        public FileVisitResult preVisitDirectoryFailed(Path dir, IOException exc) {
            return CONTINUE;
        }
    }

    static void usage() {
        System.err.println("java Find path file");
        System.exit(-1);
    }

    public static void main(String[] args) throws IOException {

        if (args.length < 2)
            usage();

        Path searchDir = Paths.get(args[0]);
        Path findFile = Paths.get(args[1]);

        // follow links when searching for files
        EnumSet<FileVisitOption> opts = EnumSet.of(FileVisitOption.FOLLOW_LINKS);
        Finder finder = new Finder(findFile);
        Files.walkFileTree(searchDir, opts, Integer.MAX_VALUE, finder);
    }
}

Update: This code has been slightly modified from when it was originally posted a few days ago. Originally, it compared the file names using the String class, but this may not provide the right result on some file systems. The comparison has been changed to the Path.equals method, which takes the type of file system into account.

Also, the example originally would only match files and not directories. By adding the comparison to the preVisitDirectory method, both files and directories will be examined.

-- Sharon Zakhour

Comments:

Post a Comment:
  • HTML Syntax: NOT allowed
About

Blog about Java technology documentation and news about Java releases.

Search

Categories
Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today