Java : Don't use the legacy File class, use new I/O APIs instead

The File class is legacy. It has several drawbacks. In this article, I will introduce you to problems of the File class and the new APIs that replace it.

Note:


Introduction

The File class is a traditional class that has existed since Java 1. If you have been using Java for a long time, you may have used it. Java 7 added new APIs of File I/O to a java.nio.file package. The new APIs include the Path interface and the Files class.

This article recommends using the new I/O APIs instead of the File class.

File class problems

The java.nio.file package defines interfaces and classes for the Java virtual machine to access files, file attributes, and file systems. This API may be used to overcome many of the limitations of the java.io.File class.

The File API documentation says that the java.nio.file package (i.e. the Path interface and the Files class) may be used to overcome many of the limitations of the File class.


・Many methods didn't throw exceptions when they failed, so it was impossible to obtain a useful error message.
・The rename method didn't work consistently across platforms.

The Java Tutorials documentation says more specific about the problems. I'm just quoting some of the problems. Please check the link for details.

Now let's actually check the code example.
An example of the File class.

// --- PowerShell ---
//PS R:\java-work> tree /F
//
//R:.
//├─empty-dir
//└─non-empty-dir
//        aaa.txt

final var emptyDir = new File("R:\\java-work\\empty-dir");
System.out.println(emptyDir.delete()); // true

final var nonEmptyDir = new File("R:\\java-work\\non-empty-dir");
System.out.println(nonEmptyDir.delete()); // false

final var nonExistentDir = new File("R:\\java-work\\XXX");
System.out.println(nonExistentDir.delete()); // false

// --- PowerShell ---
//PS R:\java-work> tree /F
//
//R:.
//└─non-empty-dir
//        aaa.txt

The File.delete method returns false if the operation fails. In the code example, the 2nd and 3rd failed. But the program can not know why it failed if it's just returned false.

Next, an example of the Path interface and the Files class.

// --- PowerShell ---
//PS R:\java-work> tree /F
//
//R:.
//├─empty-dir
//└─non-empty-dir
//        aaa.txt

//----------
// OK
final var emptyDir = Path.of("R:", "java-work", "empty-dir");
Files.delete(emptyDir);

//----------
// NG
try {
    final var nonEmptyDir = Path.of("R:", "java-work", "non-empty-dir");
    Files.delete(nonEmptyDir);
} catch (IOException e) {

    System.out.println(e);
}

// Result
// ↓
// java.nio.file.DirectoryNotEmptyException: R:\java-work\non-empty-dir

//----------
// NG
try {
    final var nonExistentDir = Path.of("R:", "java-work", "XXX");
    Files.delete(nonExistentDir);
} catch (IOException e) {
    System.out.println(e);
}

// Result
// ↓
// java.nio.file.NoSuchFileException: R:\java-work\XXX

// --- PowerShell ---
//PS R:\java-work> tree /F
//
//R:.
//└─non-empty-dir
//        aaa.txt

The Files class throws an IOException (or its subclass) if the operation fails. In the code example, throw the DirectoryNotEmptyException and the NoSuchFileException. The program could know why it failed.


Path interface, Files class advantage

An object that may be used to locate a file in a file system. It will typically represent a system dependent file path.


This class consists exclusively of static methods that operate on files, directories, or other types of files.

The problems of the File class are resolved with the Path interface and the Files class. There are other benefits as well.

Let's look at the role of each APIs.

API Role
File - has a path name.
- operates the path name. (getName, getParent etc.)
- accesses files. (mkdir, exists, delete etc.)
Path - has a path name.
- operates the path name. (getName, getParent etc.)
Files - accesses files. (createDirectory, exists, delete etc.)

It is an image of dividing the role of the File class into two.

To access files is one of the most sensitive things in a program. It would be a big problem if the user's important files were deleted by mistake...

With the File class, even code that only needs to operate the path name must be careful not to access files. In such a case, it is safe to use the Path interface. Because your code doesn't access files unless you use the Files class.

Note

  • The Path interface has some methods that cause an IOException, such as the toRealPath method and the register method.

Interoperability

Some older APIs may require the legacy File class as a parameter. It's okay when it's like that. APIs are provided for interoperability.

final Path path = Path.of("sample.txt");

final File file = path.toFile();
System.out.println(file); // sample.txt
final File file = new File("sample.txt");

final Path path = file.toPath();
System.out.println(path); // sample.txt

Conclusion

The File class is legacy. It has several drawbacks. It is better to use the Path interface and the Files class instead.


Related posts

To top of page