Java Top

Get started with Spring 5 and Spring Boot 2, through the Learn Spring course:

>> CHECK OUT THE COURSE

1. Overview

In this quick tutorial, we'll look into different ways to list files within a directory.

2. Listing

If we want to list all the files in the directory and skip further digging into sub-directories, we can simply use java.io.File#listFiles:

public Set<String> listFilesUsingJavaIO(String dir) {
    return Stream.of(new File(dir).listFiles())
      .filter(file -> !file.isDirectory())
      .map(File::getName)
      .collect(Collectors.toSet());
}

3. DirectoryStream

However, Java 7 introduced a faster alternative to File#listFiles called DirectoryStream.

Let's see what the equivalent looks like:

public Set<String> listFilesUsingDirectoryStream(String dir) throws IOException {
    Set<String> fileList = new HashSet<>();
    try (DirectoryStream<Path> stream = Files.newDirectoryStream(Paths.get(dir))) {
        for (Path path : stream) {
            if (!Files.isDirectory(path)) {
                fileList.add(path.getFileName()
                    .toString());
            }
        }
    }
    return fileList;
}

We can readily see that while DirectoryStream may be faster, it isn't part of the Stream API and isn't quite as amenable to working with it.

Also, DirectoryStream requires that we close the resource, meaning wrapping it with a try-with-resources, too.

4. Listing in Java 8

If we use Java 8, we can benefit from the new java.nio.file.Files#list method.

It returns a lazily populated Stream of entries in the directory.

Let's see a simple example:

public Set listFilesUsingFilesList(String dir) throws IOException {
    try (Stream stream = Files.list(Paths.get(dir))) {
        return stream
          .filter(file -> !Files.isDirectory(file))
          .map(Path::getFileName)
          .map(Path::toString)
          .collect(Collectors.toSet());
    }
}

If we require timely disposal of the file system resources, then we should use a try-with-resources statement. This way we make sure the stream will be closed right after the stream operations are completed.

5. Walking

Or, we can list all the files within a directory by walking it to a configured depth.

Let's use java.nio.file.Files#walk to list all the files within a directory to a given depth:

public Set<String> listFilesUsingFileWalk(String dir, int depth) throws IOException {
    try (Stream<Path> stream = Files.walk(Paths.get(dir), depth)) {
        return stream
          .filter(file -> !Files.isDirectory(file))
          .map(Path::getFileName)
          .map(Path::toString)
          .collect(Collectors.toSet());
    }
}

Of course, remember to use try-with-resources so the file handle for dir gets closed properly.

Or, if we want to have more control over what happens with each file visited, we can also supply a visitor implementation:

public Set<String> listFilesUsingFileWalkAndVisitor(String dir) throws IOException {
    Set<String> fileList = new HashSet<>();
    Files.walkFileTree(Paths.get(dir), new SimpleFileVisitor<Path>() {
        @Override
        public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
          throws IOException {
            if (!Files.isDirectory(file)) {
                fileList.add(file.getFileName().toString());
            }
            return FileVisitResult.CONTINUE;
        }
    });
    return fileList;
}

This is handy when we want to do additional reading, moving, or deleting of files as we go.

6. Conclusion

In this quick tutorial, we explored different ways to list files within a directory.

As always, the full source code of the examples is available over on GitHub.

Java bottom

Get started with Spring 5 and Spring Boot 2, through the Learn Spring course:

>> CHECK OUT THE COURSE
Generic footer banner
Comments are closed on this article!