Trail: Essential Classes
Lesson: Basic I/O
Section: File I/O (featuring NIO.2)
Creating and Reading Directories
Home Page > Essential Classes > Basic I/O
Creating and Reading Directories
Some of the methods previously discussed, such as delete, work on files, links and directories. But how do you list all the directories at the top of a file system? How do you list the contents of a directory or create a directory?

This section covers functionality specific to directories:

Listing a File System's Root Directories

You can easily list all the root directories for a file system using the FileSystem.getRootDirectories method. This method returns an Iterable which allows you to use the enhanced for statement to iterate over all the root directories.

The following code snippet prints the root directories for the default file system:

Iterable<Path> dirs = FileSystems.getDefault().getRootDirectories();
for (Path name: dirs) {
    System.err.println(name);
}

Creating a Directory

You can easily create a new directory using the createDirectory(FileAttribute<?>) method. If you don't specify any arguments, the new directory will have default attributes. Here is the simplest example:

Path dir = ...;
try {
    path.createDirectory();
} catch (IOException x) {
    System.err.println(x);
}

The following code snippet creates a new directory (on a POSIX file system) that has specific permissions:

Set<PosixFilePermission> perms = PosixFilePermissions.fromString("rwxr-x---");
FileAttribute<Set<PosixFilePermission>> attr = PosixFilePermissions.asFileAttribute(perms);
try {
     file.createDirectory(attr);
} catch (IOException x) {
     System.err.println(x);
}

To create a directory several levels deep when one or more of the parent directories may not yet exist, you can use the convenience method, createDirectories(Path, FileAttributes<?>), in the Files class. As with the createDiretory(FileAttribute<?>) method, you can specify an optional set of initial file attributes. The following code snippet uses default attributes:

try {
     Files.createDirectories(Paths.get("foo/bar/test"));
} catch (IOException x) {
     System.err.println(x);
}

The directories are created, as needed, from the top down. In the case of foo/bar/test, if the foo directory does not exist, it is is created. Next, the bar directory is created, if needed, and, finally, the test directory is created.

It is possible for this method to fail after creating some, but not all, of the parent directories.

Listing a Directory's Contents

You can easily list all the contents of a directory using the newDirectoryStream method. This method returns an object that implements the DirectoryStream interface. The class that implements the DirectoryStream interface also implements Iterable, so you can iterate through the directory stream, reading all of the objects. This approach scales well to very large directories.


Remember: The returned DirectoryStream is a stream! Don't forget to close the stream in the finally block.

The following code snippet shows how to print the contents of a directory:

Path dir = ...;
DirectoryStream<Path> stream = null;
try {
    stream = dir.newDirectoryStream();
    for (Path file: stream) {
        System.out.println(file.getName());
    }
} catch (IOException x) {
    //IOException can never be thrown by the iteration.
    //In this snippet, it can only be thrown by newDirectoryStream.
    System.err.println(x);
} finally {
    if (stream != null) stream.close();
}

The Path objects returned by the iterator are the names of the entries resolved again the directory. So, if you are listing the contents of the /tmp directory, the entries are returned with the form /tmp/a, /tmp/b, and so on.

This method returns the entire contents of a directory — files, links, subdirectories and hidden files. If you want to be more selective about the contents that are retrieved, you can use one of the other newDirectoryStream methods, described later in this page.

Filtering a Directory Listing using Globbing

Say you want to fetch only files and subdirectories where each name matches a particular pattern. You can accomplish this using the newDirectoryStream(String) method which provides a built-in glob filter. If you are not familiar with glob syntax, see What is a Glob?.

For example, the following snippet lists files relating to Java — .class, .java and .jar files.:

Path dir = ...;
DirectoryStream<Path> stream = null;
try {
    stream = dir.newDirectoryStream("*.{java.class,jar}");
    for (Path entry: stream) {
        System.out.println(entry.getName());
    }
} catch (IOException x) {
    //IOException can never be thrown by the iteration.
    //In this snippet, it can only be thrown by newDirectoryStream.
    System.err.println(x);
} finally {
    if (stream != null) stream.close()
}

Writing Your Own Directory Filter

Perhaps you want to filter the contents of a directory based on some condition other than pattern matching. You can create your own filter by implementing the DirectoryStream.Filter<T> interface. This interface consists of one method, accept, which determines whether a file fulfills the search requirement.

For example, the following code snippet implements a filter that retrieves only directories:

DirectoryStream.Filter<Path> filter = newDirectoryStream.Filter<Path>() {
    public boolean accept(Path file) {
        try {
            boolean isDirectory = Attributes.readBasicFileAttributes(file).isDirectory();
            return (isDirectory);
        } catch (IOException x) {
            //Failed to determine if it's a directory.
            System.err.println(x);
            return false;
        }
    }
};

Once the filter has been created, it can be invoked using the newDirectoryStream(DirectoryStream.Filter<? super Path>) method. The following code snippet uses the "isDirectory" filter to print only the directory's subdirectories to standard out:

Path dir = ...;
DirectoryStream<Path> stream = null;
try {
    stream = dir.newDirectoryStream(filter);
    for (Path entry: stream) {
        System.out.println(entry.getName());
    }
} catch (IOException x) {
    System.err.println(x);
} finally {
    stream.close();
}

This method is used to filter a single directory only. If you wanted to, say, find all the subdirectories in a file tree, you would use the mechanism for Walking the File Tree.

Previous page: Random Access Files
Next page: Links, Symbolic or Otherwise