Friday, October 19, 2012

Java 7: File Filtering using NIO.2 - Part 1

Hello all. NIO.2 is a new API for I/O operations included in the JDK since Java 7. With this new API, you can perform the same operations performed with java.io plus a lot of great functionalities such as: Accessing file metadata and watching for directory changes, among others. Obviously, the java.io package is not going to disappear because of backward compatibility, but we are encouraged to start using NIO.2 for our new I/O requirements. In this post, we are going to see how easy it is to filter the contents of a directory using this API. There are 3 ways in order to do so, that's why this post is Part 1.

What you need
NetBeans 7+ or any other IDE that supports Java 7
JDK 7+

Filtering content of a directory is a common task in some applications and NIO.2 makes it really easy. The classes and Interfaces we are going to use are described next:
  • java.nio.file.Path: Interface whose objects may represent files or directories in a file system. It's like the java.io.File but in NIO.2. Whatever I/O operation you want to perform, you need an instance of this interface.
  • java.nio.file.DirectoryStream: Interface whose objects iterate over the content of a directory.
  • java.nio.file.Files: Class with static methods that operates on files, directories, etc.

The way we are going to filter the contents of a directory is by using glob patterns, which are like regular expressions but simpler. The pattern is matched against the name of the files, directories, etc. That live inside the directory. This is important to remember, using this method you can only filter by the name of the file, directory, etc.
For more information about globbing, check this wiki. Also, there is some documentation about globbing patterns in the Java Docs.

So, let's suppose that we have a directory called Images, and we need to iterate over the files inside this directory, but we only need the .png files. We have to follow this steps in order to do so:
  1. Obtain a java.nio.file.Path instance which points to the directory Images.
  2. Open a new java.nio.file.DirectoryStream using the java.nio.file.Files class and passing the directory and the pattern (*.png) as parameters.
  3. Iterate over the content of the directory using the java.nio.file.DirectoryStream instance.
Next is the source code of a method that scans a directory using the pattern passed as parameter:

//in a class...
    
    /**
     * Scans the directory using the glob pattern passed 
     * as parameter. 
     * @param folder directory to scan
     * @param pattern glob pattern (filter)
     */
    private static void scan(String folder, String pattern) {
        //obtains the Images directory in the app directory
        Path dir = Paths.get(folder);
        //the Files class offers methods for validation
        if (!Files.exists(dir) || !Files.isDirectory(dir)) {
            System.out.println("No such directory!");
        }
        //Try with resources... so nice!
        try (DirectoryStream<path> ds = 
                    Files.newDirectoryStream(dir, pattern)) {
            //iterate over the content of the directory
            int count = 0;
            for (Path path : ds) {
                System.out.println(path.getFileName());
                count++;
            }
            System.out.println();
            System.out.printf("%d Files match the pattern"
                                                     , count);
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }


Following is the result of the execution on my windows machine:



And on my Linux virtual machine:


That's something I love from Java, Write once, run everywhere! I hope you enjoyed this post, there are more ways to filter the content of a directory and we'll explore them in future posts.

Click here to download the complete source code.

See ya!

References:

Reese Richard and Reese Jennifer (2012). Java 7 New Features Cookbook. United Kingdom: Packt Publishing Ltd.