EOFException when reading files with ObjectInputStream

2012-10-02 java

I basically have a similar problem as stated here: EOFexception in Java when reading objectinputstream, but I don't find an answer with clean code.

The answer states that the ObjectInputStream#readObject will throw the exception when the reader reachs the End Of File. After looking in the web for a solution, I haven't found a solution. Could be a good and clean solution for this case?

Note: I have tried this (but it looks ugly and is not clean code). I'm looking for a better solution:

ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
try {
    Object o;
    while ((o = ois.readObject()) != null) {
        if (o instanceof MyClass) {
            MyClass m = (MyClass)o;
            //use the object...
        }
    }
} catch (EOFException eofex) {
    //do nothing
}  catch (IOException ioex) {
    throw ioex;
    //I have another try/catch block outside to control the life of the ObjectInputStream
}
//later in the code...
ois.close();

Answers

That's what's supposed to happen. Your code is wrong. Check the Javadoc. readObject() only returns null if you wrote a null. It doesn't say anything about returning a null at EOF. Looping until readObject() returns null will only stop if you ever wrote a null via writeObject(), and if you didn't you will get an EOFException.

@EJP's answer has nailed it.

However if you are a paid-up member of the "exceptions should't be used for normal flow control" club* then you can avoid having to catch the exception if you can use some other means to determine when to stop; for example

  • You could start the stream with a count sent as an int or an Integer object.
  • You could mark the end the stream by sending a null.
  • You could mark the end the stream by sending a special object that means "this is the end". It does not need to be a MyClass instance.
  • You could send a List<MyClass> ... though that means that you can't "stream" the objects.

Note that this implies that you are able to change the sender-side code ...


* Membership of this club requires either the ability to assimilate circular arguments, or willingness to blindly accept dogma as truth. :-)


Rather than repeat the arguments ad nauseam, here are some links to some of my answers related to the "normal flow control" debate:

If you read through them, you will see that I don't come down firmly on either side of the fence. Rather, my view is that you should understand the trade-offs, and make a decision about whether exceptions are appropriate or not on a case-by-case basis.

You could try this:

boolean check=true;
while (check) {
   try{
       System.out.println(ois.readObject());
   } catch(EOFException ex){
       check=false;
   }
}

While readObject() doesn't return NULL when it hits the end of a file, if you control the file from it's inception you could always add NULL right before closing your output stream. It will get passed as an object, but you can then test for end of file as such:

Boolean complete = false;
ObjectInputStream in = <...>

while(complete != true) {
    Object test = (Object)in.readObject();
    if(test != null) { someArrayList.add(test); }
        else { complete = true; }
}

I encountered this error because I had forgot to close an ObjectOutputStream in the code that wrote the data. Once I wrote the data again with code that closed the output stream the data was able to be read in fine.

Related