Need to list all files in a given directory with your Java application? 

Good news: it's a breeze.

And in this guide I'll show you how to do it using Java NIO.

But first, we need to get some prequisites out of the way.

Going Bi-Curious With Your Predicate

The solution I'll present in this guide involves the use of BiPredicate. It's a functional interface that doesn't get a whole lot of air time.

And yes, it's similar to Predicate. Both functional interfaces return a boolean.

The difference is that BiPredicate accepts two input paramters whereas Predicate only accepts one. It's useful when you may need to return a boolean based on the values of two different objects.

Flying With Files

There are plenty of classes in the Java NIO API. Some of them are singluar (File and Path) while others are plural (Files and Paths). It's tough to remember which class does what.

For the purposes of this guide, I'll use the two plurals. Specifically, I'll opt for the Files.find() and Paths.get() methods.

If you're a bit of a Java NIO veteran, you might be wondering why I'm not going with Files.walk() when it comes to listing files. The answer is because this solution offers a little more efficiency by avoiding multiple retrievals of the file attributes.

At least: that's what the docs say.

So Files.find() it is then.

But that static find() method requires a few parameters. Let's look at those next.

Looking for a Few Good Parameters

The first parameter in Files.find() is a Path object. It represents the directory with the files you want to list.

It's easy to convert a string that represents a directory to a Path object with the aid of Paths.get(). I'll show you that in a moment.

The second parameter is an integer. It represents how "deep" you want to go when finding files.

If you only want to list files in the directory specified by the Path object, use 1 for that parameter. If you want to list files in subdirectories as well, use Integer.MAX_VALUE.

If you want to specify how "deep" you want to go when searching subdirectories, put in the appropriate integer. For example, if you want to only search three directories deep, use 4 (the top directory counts as 1).

The third parameter is the BiPredicate. It's what you'll use to determine if the Path object in the Stream is a regular file or directory.

You'll only list it if it's a regular file.

Okay, now that we know a little more about what's required, let's look at the code.

The Code

Suppose you want to list all the files in /etc/careydevelopment. Here's how to make that happen using Files.find():

final String path = "/etc/careydevelopment";
            
try (Stream<Path> paths = Files.find(Paths.get(path),
        1,
        (filePath, fileAttr) -> fileAttr.isRegularFile())) {
    
    paths.forEach(System.err::println);
}

The first line instantiates a String object that represents a directory in the underlying file system.

But pay attention to what's happening in the second line. It's using try-with-resources.

You have to do it that way.

Straight out of the Javadoc: "This method must be used within a try-with-resources statement or similar control structure to ensure that the stream's open directories are closed promptly after the stream's operations have completed."

So... you have to do it that way.

There's a lot happening inside the try parentheses, though. It's using Files.find() to get all the regular files in the directory specified by path.

The first parameter just gets a Path object using Paths.get(). I'd told you I'd show you how to do that.

The second parameter, an integer of 1, tells the find() method to only list files in the directory specified by the Path object. It won't list files from any of the subdirectories.

That third parameter is the BiPredicate. The two input parameters are the current Path object in the stream and its corresponding BasicFileAttributes object.

The code uses that second object to determine if the Path object points to a regular file. If so, then it gets included in the final Stream object.

Within the try block the code simply prints out each file.

And that's it. Run that beast and it will show you all the files in the /etc/careydevelopment directory.

Wrapping It Up

There you go. That's how you use Java NIO to list all files in a particular directory.

Feel free to take the code above and make it your own. Update it. Tinker with it. Massage it.

Just make sure you have fun!

Photo by Mike from Pexels