Java: List Files in a Directory

Introduction

A lot of applications handle files in some way and file manipulation is one of the core knowledges in any programming language.

In order to manipulate files, we need to know where they're located. Having an overview of files in a directory is paramount if we want to accomplish this, especially if we can perform operations on them through iteration. There are several ways to do this in Java, which we'll show throughout this article.

For the sake of simplicity, all examples will be written for the following file tree:

Programming
|-- minimax.c
|-- super_hack.py
|-- TODO.txt
`-- CodingMusic
    |-- Girl Talk - All Day.mp3
    |-- Celldweller - Frozen.mp3
    |-- Lim Taylor - Isn't It Wonderful.mp3
    `-- Radiohead - Everything in Its Right Place.mp3

File.list()

The simplest method to list the names of files and folders in a given directory, without traversing the sub-directories, is the helper method .list(), which returns an array of Strings.

We do this by using the .list() method on a File instance:

public class Pathnames {

    public static void main(String[] args) {
        // Creates an array in which we will store the names of files and directories
        String[] pathnames;

        // Creates a new File instance by converting the given pathname string
        // into an abstract pathname
        File f = new File("D:/Programming");

        // Populates the array with names of files and directories
        pathnames = f.list();

        // For each pathname in the pathnames array
        for (String pathname : pathnames) {
            // Print the names of files and directories
            System.out.println(pathname);
        }
    }
}

Using a simple for-each loop, we iterate through the array and print out the Strings.

CodingMusic
minimax.c
super_hack.py
TODO.txt

Using this approach, all of the items in the CodingMusic directory aren't shown, and a downside to this approach is that we can't really do anything to the files themselves. We're just getting their names. It's useful when we just want to take a look at the files at face-value.

FilenameFilter

Another thing we can do with the .list() method is to create a FilenameFilter to return only the files we want:

File f = new File("D:/Programming");

// This filter will only include files ending with .py
FilenameFilter filter = new FilenameFilter() {
        @Override
        public boolean accept(File f, String name) {
            return name.endsWith(".py");
        }
    };

// This is how to apply the filter
pathnames = f.list(filter);

Running this piece of code would yield:

super_hack.py

File.listFiles()

Similar to the previous method, this one can be used to return the names of files and directories, but this time we get them as an array of File objects, which gives us the ability to directly manipulate them:

public class Pathnames {
    public static void main(String args[]) {

        // try-catch block to handle exceptions
        try {
            File f = new File("D:/Programming");

            FilenameFilter filter = new FilenameFilter() {
                @Override
                public boolean accept(File f, String name) {
                    // We want to find only .c files
                    return name.endsWith(".c");
                }
            };

            // Note that this time we are using a File class as an array,
            // instead of String
            File[] files = f.listFiles(filter);

            // Get the names of the files by using the .getName() method
            for (int i = 0; i < files.length; i++) {
                System.out.println(files[i].getName());
            }
        } catch (Exception e) {
            System.err.println(e.getMessage());
        }
    }
}

Output:

minimax.c

Now, let's traverse deeper into the file system using recursion and some more methods to use on the File object:

public class ListFilesRecursively {
    public void listFiles(String startDir) {
        File dir = new File(startDir);
        File[] files = dir.listFiles();

        if (files != null && files.length > 0) {
            for (File file : files) {
                // Check if the file is a directory
                if (file.isDirectory()) {
                    // We will not print the directory name, just use it as a new
                    // starting point to list files from
                    listDirectory(file.getAbsolutePath());
                } else {
                    // We can use .length() to get the file size
                    System.out.println(file.getName() + " (size in bytes: " + file.length()+")");
                }
            }
        }
    }
    public static void main(String[] args) {
        ListFilesRecursively test = new ListFilesRecursively();
        String startDir = ("D:/Programming");
        test.listFiles(startDir);
    }
}

Output:

Girl Talk - All Day.mp3 (size in bytes: 8017524)
Celldweller - Frozen.mp3 (size in bytes: 12651325)
Lim Taylor - Isn't It Wonderful.mp3 (size in bytes: 6352489)
Radiohead - Everything in Its Right Place.mp3 (size in bytes: 170876098)
minimax.c (size in bytes: 20662)
super_hack.py (size in bytes: 114401)
TODO.txt (size in bytes: 998)

Files.walk()

In Java 8 and later we can use the java.nio.file.Files class to populate a Stream and use that to go through files and directories, and at the same time recursively walk all subdirectories.

Note that in this example we will be using Lambda Expressions:

public class FilesWalk {
    public static void main(String[] args) {
        try (Stream<Path> walk = Files.walk(Paths.get("D:/Programming"))) {
            // We want to find only regular files
            List<String> result = walk.filter(Files::isRegularFile)
                    .map(x -> x.toString()).collect(Collectors.toList());

            result.forEach(System.out::println);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Here, we've populated a Stream using the .walk() method, passing a Paths argument. The Paths class consists of static methods that return a Path based on a String URI - and using a Path, we can locate the file easily.

The Path, Paths, Files, and many other classes belong to the java.nio package, which was introduced in Java 7 as a more modern way to represent files in a non-blocking way.

Then, using the Collections Framework, a list is generated.

Running this piece of code will yield:

D:\Programming\Coding Music\Radiohead - Everything in Its Right Place.mp3
D:\Programming\Coding Music\Lim Taylor - Isn't It Wonderful.mp3
D:\Programming\Coding Music\Celldweller - Frozen.mp3
D:\Programming\Coding Music\Girl Talk - All Day.mp3
D:\Programming\minimax.c
D:\Programming\super_hack.py
D:\Programming\TODO.txt

Conclusion

Handling files in some way is a core task for most programming languages, and this includes the ability to list and find files in the file system. In order to manipulate files, we need to know where they're located. Having an overview of files in a directory is paramount if we want to accomplish this, especially if we can perform operations on them through iteration.

In this article we showed a number of different ways in Java to list files on the file system, using both linear and recursive approaches.