Java Exception Handling

Java Exception Handling – EOFException

Making our way through our detailed Java Exception Handling series, today we’ll tackle the EOFException. Most developers will probably recognize that the acronym EOF in this exception name usually stands for “end of file”, which is exactly the case here. When an EOFException is thrown in Java, this indicates that the end of the file or stream has been reached unexpectedly.

In this article we’ll examine the EOFException in more detail, starting with where it sits in the larger Java Exception Hierarchy. We’ll also go over some functional sample code that shows basic file manipulation, and how failing to improperly handle reaching the end of file or memory streams will result in uncaught EOFExceptions. Let’s get to it!

The Technical Rundown

All Java errors implement the java.lang.Throwable interface, or are extended from another inherited class therein. The full exception hierarchy of this error is:

Full Code Sample

Below is the full code sample we’ll be using in this article. It can be copied and pasted if you’d like to play with the code yourself and see how everything works.

When Should You Use It?

Since the appearance of an EOFException simply indicates that the end of the file or memory stream was reached, the best way to show how to properly use and handle this exception is in code, so let’s jump right into our sample.

We start with a basic Book class that contains a few fields, which we’ll be using to create some real-world objects to output to a local file.

In our Main program class we start by defining a basic List<Book> private property called DATA, along with the path to our FILE:

Next we have the WriteBooksToFile() method, which does just as the name suggests:

By using a DataOutputStream instance we’re able to loop through the collection of Books found in our DATA property and create a new string via the writeUTF(...) method. Once complete, we close the stream, and all is taken care of. Executing this method produces the following output to the log:

To confirm the formatted Book strings are being locally saved we can open up the local books.txt file. Here’s the current contents of that file (Note that this file is actually in binary, even though it mostly appears as plain text):

Cool. Now, to retrieve the data that was saved to books.txt we start with the ReadBooksFromFileImproperly() method:

Executing this method produces the following output:

Everything seems to be working propertly at first but, as you can see, once we reach the end of the file an EOFException is thrown, which we’ve caught and output to the log. However, this method isn’t configured very well, since any other unexpected exception (such as an IOException) might take precedent over the expected EOFException, which we’ll get every time.

Therefore, the recommended way to handle reaching the end of a file in this sort of scenario is to enclose the stream-reading statements in their very own try-catch block, to explicitly handle EOFExceptions. Once the expected EOFException is caught, this can be used as control flow statement to redirect execution flow to the next proper statement in the code. While this sort of practice is usually frowned on in most languages, in this particular case it is the only way to handle EOFExceptions. To illustrate one such example let’s look at the modified ReadBooksFromFile() method:

As you can see, this method contains quite a bit more code than the improper version, but it explicitly surrounds the statements that are reading from the stream with try-catch block to handle EOFExceptions. When an EOFException is caught, the break; statement breaks the infinite while (true) loop and continues executing the rest of the method, like normal. Additionally, we can then perform all our normal exception handling with the outer try-catch block covering the entirety of the method code.

The Airbrake-Java library provides real-time error monitoring and automatic exception reporting for all your Java-based projects. Tight integration with Airbrake’s state of the art web dashboard ensures that Airbrake-Java gives you round-the-clock status updates on your application’s health and error rates. Airbrake-Java easily integrates with all the latest Java frameworks and platforms like Spring, Maven, log4j, Struts, Kotlin, Grails, Groovy, and many more. Plus, Airbrake-Java allows you to easily customize exception parameters and gives you full, configurable filter capabilities so you only gather the errors that matter most.

Check out all the amazing features Airbrake-Java has to offer and see for yourself why so many of the world’s best engineering teams are using Airbrake to revolutionize their exception handling practices!