Listing and filtering directory contents in NIO.2

There hasn’t been much happening in the area of listing directory contents until the release of Java 7. But since NIO.2 introduced a new way to do this it might be worth it to cover this area. One of big pluses of NIO.2 is the ability to use listing and filtering at once in one method call. This provides an elegant solution to most of listing/filtering needs related to work with a file system.

Listing root directories

Unless we are working with relative paths we need to be aware of the environment where our application lives, so we can define absolute paths. Since file systems are usually hierarchical structures there is at least one root directory. To properly address files and directories we need to be able to list all these root directories. To do this, we turn to the FileSystem instance itself to use its method getRootDirectories, which is an alternative to Java 6 construct File.listRoots().

Iterable<Path> it = FileSystems.getDefault().getRootDirectories();

System.out.println("Root file system locations: " + Sets.newHashSet(it));

*Please note that class Sets is not part of JDK, but comes from Google’s Guava library. I used it here, just for convenience to get nicely formated string representation of root directories.

With following output:

Root file system locations: C:\, D:\, E:\, F:\, G:\, H:\, I:\,

Listing and filtering directory contents

Standard task when working with file system is to list or filter files within given directory. We might need to modify, analyze or simply list them – whatever the reason, class java.nio.file.Files has our backs. It offers three variants of method newDirectoryStream that return object of type DirectoryStream<Path> to allow us to iterate over the entries in a directory. Here we see an apparent difference between current and prior versions of IO library (returning simple arrays) preventing NullPointerException. Following example shows how simple it is to list contents of given directory:

Path directoryPath = Paths.get("C:", "Program Files/Java/jdk1.7.0_40/src/java/nio/file");

if (Files.isDirectory(directoryPath)) {
    try (DirectoryStream<Path> stream = Files.newDirectoryStream(directoryPath)) {
        for (Path path : stream) {
            System.out.println(path);
        }
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}

Please notice the use of isDirectory checking method that prevents NotDirectoryException. Also note the use of the try-with-resources construct – DirectoryStream is both AutoCloseable and Closeable (meaning it needs to be closed at some time) so try-with-resources comes in handy. Code returns following output:

...
C:\Program Files\Java\jdk1.7.0_40\src\java\nio\file\CopyOption.java
C:\Program Files\Java\jdk1.7.0_40\src\java\nio\file\DirectoryIteratorException.java
C:\Program Files\Java\jdk1.7.0_40\src\java\nio\file\DirectoryNotEmptyException.java
C:\Program Files\Java\jdk1.7.0_40\src\java\nio\file\DirectoryStream.java
C:\Program Files\Java\jdk1.7.0_40\src\java\nio\file\FileAlreadyExistsException.java
C:\Program Files\Java\jdk1.7.0_40\src\java\nio\file\Files.java
C:\Program Files\Java\jdk1.7.0_40\src\java\nio\file\FileStore.java
C:\Program Files\Java\jdk1.7.0_40\src\java\nio\file\FileSystem.java
C:\Program Files\Java\jdk1.7.0_40\src\java\nio\file\FileSystemAlreadyExistsException.java
...

To ensure universal usability of DirectoryStream<Path> we can filter using two basic mechanisms:

  • newDirectoryStream(Path dir, String glob)
    • Filtering using GLOB
  • newDirectoryStream (Path dir, DirectoryStream.Filterfilter)
    • Filtering using  DirectoryStream.Filter

Filtering with GLOB pattern

First of all we need to know what a GLOB is. GLOB patterns are string expressions that follow specific syntax rules and they are used for matching purposes. Please refer to the following article for more information on GLOBs and GLOB syntax. When it comes to filtering using GLOBs, Files class provides us with an easy way to do so. Lets take a look at following example.

Path directoryPath = Paths.get("C:", "Program Files/Java/jdk1.7.0_40/src/java/nio/file");

if (Files.isDirectory(directoryPath)) {
    try (DirectoryStream<Path> stream = Files.newDirectoryStream(directoryPath, "File*Exception*")) {
        for (Path path : stream) {
            System.out.println(path);
        }
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}

With following output:

C:\Program Files\Java\jdk1.7.0_40\src\java\nio\file\FileAlreadyExistsException.java
C:\Program Files\Java\jdk1.7.0_40\src\java\nio\file\FileSystemAlreadyExistsException.java
C:\Program Files\Java\jdk1.7.0_40\src\java\nio\file\FileSystemException.java
C:\Program Files\Java\jdk1.7.0_40\src\java\nio\file\FileSystemLoopException.java
C:\Program Files\Java\jdk1.7.0_40\src\java\nio\file\FileSystemNotFoundException.java

Filtering with DirectoryStream.Filter

When the task at hand requires more complex filtering options rather than just simple file name matching, we need to implement interface DirectoryStream.Filter<Path>. This is the most powerful filtering option available at our disposal since we have an access to the rest of the application and might use third party libraries. Following example shows such a situation with two filtering conditions:

  • File size must be an even number
  • Time of execution in milliseconds must be an even number
Path directoryPath = Paths.get("C:", "Program Files/Java/jdk1.7.0_40/src/java/nio/file");
DirectoryStream.Filter<Path> filter = new Filter<Path>() {

    @Override
    public boolean accept(Path entry) throws IOException {
        long size = Files.readAttributes(entry, BasicFileAttributes.class, LinkOption.NOFOLLOW_LINKS).size();
        long milis = new Date().getTime();

        boolean isSizeEvenNumber = size % 2 == 0;
        boolean isTheTimeRight = milis % 2 == 0;

        return isTheTimeRight && isSizeEvenNumber;
    }
};

if (Files.isDirectory(directoryPath)) {
    try (DirectoryStream<Path> stream = Files.newDirectoryStream(directoryPath, filter)) {
        for (Path path : stream) {
            System.out.println(path);
        }
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}

With following output:

C:\Program Files\Java\jdk1.7.0_40\src\java\nio\file\DirectoryStream.java
C:\Program Files\Java\jdk1.7.0_40\src\java\nio\file\FileAlreadyExistsException.java
C:\Program Files\Java\jdk1.7.0_40\src\java\nio\file\Files.java
C:\Program Files\Java\jdk1.7.0_40\src\java\nio\file\NotDirectoryException.java
C:\Program Files\Java\jdk1.7.0_40\src\java\nio\file\NotLinkException.java
C:\Program Files\Java\jdk1.7.0_40\src\java\nio\file\package-info.java
C:\Program Files\Java\jdk1.7.0_40\src\java\nio\file\WatchEvent.java
C:\Program Files\Java\jdk1.7.0_40\src\java\nio\file\WatchService.java

*Please note that based on used conditions filtered files may differ per execution.

Do you want to know how to develop your skillset to become a Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you two of our best selling eBooks for FREE!

JPA Mini Book

Learn how to leverage the power of JPA in order to create robust and flexible Java applications. With this Mini Book, you will get introduced to JPA and smoothly transition to more advanced concepts.

JVM Troubleshooting Guide

The Java virtual machine is really the foundation of any Java EE platform. Learn how to master it with this advanced guide!

Given email address is already subscribed, thank you!
Oops. Something went wrong. Please try again later.
Please provide a valid email address.
Thank you, your sign-up request was successful! Please check your e-mail inbox.
Please complete the CAPTCHA.
Please fill in the required fields.

Leave a Reply


9 − eight =



Java Code Geeks and all content copyright © 2010-2014, Exelixis Media Ltd | Terms of Use | Privacy Policy
All trademarks and registered trademarks appearing on Java Code Geeks are the property of their respective owners.
Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries.
Java Code Geeks is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.
Do you want to know how to develop your skillset and become a ...
Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you two of our best selling eBooks for FREE!

Get ready to Rock!
You can download the complementary eBooks using the links below:
Close