1. Introduction
FileNotFoundException is a common checked exception when we work with files in Java.
In this tutorial, we’ll discuss when FileNotFoundException can occur and common ways of handling it through examples.
2. When Is the Exception Thrown?
As indicated in Java’s API documentation, FileNotFoundException can be thrown when:
- We try to access a non-existent file
- The file exists but is inaccessible for some reason, for example, attempting to write to a read-only file
Next, let’s see some examples.
For simplicity, we’ll use JUnit 5 and it’s temporary directory support for demonstrations in this tutorial.
2.1. When a File Doesn’t Exist
Let’s first create a Path instance with the @TempDir annotation, which will be used as the root temporary directory for all tests:
@TempDir
private Path tempDir;
Next, let’s try to access a non-existent file and see what will happen:
File notExistFile = tempDir.resolve("dummy.notExist").toFile();
assertThrows(FileNotFoundException.class, () -> {FileReader fileReader = new FileReader(notExistFile);});
As the example shows, we created a FileReader object on notExistFile. As a result, FileNotFoundException was thrown.
2.2. When a File Is Inaccessible
Now, let’s see what happens if we attempt to write to a read-only file:
File readOnlyFile = tempDir.resolve("dummy.ReadOnly").toFile();
// first creating a read-only file
try (PrintWriter printWriter = new PrintWriter(new FileWriter(readOnlyFile))) {
printWriter.println("Hi there!");
readOnlyFile.setReadOnly();
}
assertTrue(readOnlyFile.exists());
assertFalse(readOnlyFile.canWrite());
// now we create a FileWriter on the read-only file
assertThrows(FileNotFoundException.class, () -> {
FileWriter fileWriter = new FileWriter(readOnlyFile);
});
As the code above shows, we first created a readOnlyFile with some content (“Hi there!”) using try-with-resources. Then, FileNotFoundException was raised when we tried to instantiate a FileWriter instance on the read-only file.
3. Handling FileNotFoundException
In this section, we’ll show some common approaches to handling a FileNotFoundException in Java.
3.1. Log the Exception When It Occurs
Sometimes, when a FileNotFoundException isn’t a critical error, it shouldn’t stop the execution. In this case, we may want to log it for further analysis:
Path notExistFile = tempDir.resolve("dummy.notExist");
try {
FileReader fileReader = new FileReader(notExistFile.toFile());
} catch (FileNotFoundException ex) {
LOG.warn("Error Occurred when reading the optional file " + notExistFile, ex);
}
When we execute this code, we see the following output:
[2024-09-04 15:19:55,069]-[main] WARN ... - Error Occurred when reading the optional file /path/to/dummy.notExist
java.io.FileNotFoundException: /path/to/dummy.notExist (No such file or directory)
at java.base/java.io.FileInputStream.open0(Native Method)
...
In this example, we log the FileNotFoundExcetion as a “warning” with a meaningful message.
3.2. Raising a Custom Exception
Sometimes, when a FileNotFoundException occurs, we must stop the current execution. However, we want to wrap it in a customer exception and leave this decision to the upper layers of the application.
Let’s first create a ConfiguraionException class:
class ConfigurationException extends RuntimeException {
ConfigurationException(String string, FileNotFoundException ex) {
super(string, ex);
}
}
Next, let’s create a method that reads some configurations from a file:
String readConfig(Path path) throws IOException {
try (BufferedReader reader = new BufferedReader(new FileReader(path.toFile()))){
return reader.readLine();
} catch (FileNotFoundException ex) {
throw new ConfigurationException("Reading configuration file failed", ex);
}
}
As we can see, if we encounter FileNotFoundException, we wrap it in our ConfigurationException and ask the caller to decide how to deal with this case — for example, creating a new configuration file or using some default configurations:
assertThrows(ConfigurationException.class, () -> readConfig(tempDir.resolve("dummy.notExist")));
The above test shows that readConfig() throws ConfigurationException when we pass a non-existent file to it.
3.3. With Some Recovery Actions
In some cases, we might want to perform some recovery actions when the exception occurs. Let’s see an example:
public String readOrCreateFileWithContent(Path path, String defaultValue) {
try (BufferedReader reader = new BufferedReader(new FileReader(path.toFile()))) {
return reader.readLine();
} catch (FileNotFoundException e) {
try (PrintWriter writer = new PrintWriter(new FileWriter(path.toFile()))) {
writer.print(defaultValue);
return defaultValue;
} catch (IOException ex) {
throw new RuntimeException("IOException when trying to create the file", ex);
}
} catch (IOException e) {
throw new RuntimeException("IOException when trying to read the file", e);
}
}
As the method shows, we first try to read a line from the desired file. If the file doesn’t exist, we create a file with the given path and write defaultValue to it as a recovery:
Path path = tempDir.resolve("dummy.notExist");
assertFalse(path.toFile().exists()); // file doesn't exist
String defaultValue = "the-default-value";
String value = readOrCreateFileWithContent(path, defaultValue);
assertEquals(defaultValue, value);
assertEquals(defaultValue, Files.readString(path));
In this test, we call readOrCreateFileWithContent() by passing a non-existent file path. As a result, the file is automatically created with defaultValue as its content.
4. Conclusion
In this article, we’ve discussed when a FileNotFoundException can occur and explored several common approaches to handle this exception.
The code backing this article is available on GitHub. Once you're
logged in as a Baeldung Pro Member, start learning and coding on the project.