Avoid ObjectInputStream.readObject() from throwing EOFException at End Of File in java


Before going into this post I’ll strongly recommend you to have knowledge of how objects are Serialized and DeSerialized in java.

During deserialization process when file is read till end using readObject() in while loop then EOFException is thrown as we saw in DeSerialization program. Java Api doesn’t provide any elegant solution to signify end the file.
Generally what we could except at EOF(end of file) is null but that doesn’t happen.


So, we’ll try to address the problem because catching EOFException and interpreting it as EOF is not the elegant solution because sometimes you may fail to detect a normal EOF of a file that has been truncated.

So, lets discuss best possible solution to address the problem >
  • Solution 1) You may persist some count in file during serialization process to find out exactly how many object were actually serialized and simply use for loop in place of while loop in deserialization process.
Or,
  • Solution 2) I’ll recommend you this solution, probably the best solution
    • Create a class EofIndicatorClass which implements Serializable interface.
    • During serialization >
      • Write instance of EofIndicatorClass at EOF during serialization to indicate EOF during deSerialization process.
    • During serialization >
      • If oin.readObject() returns instanceof EofIndicatorClass that means it's EOF, exit while loop and EOFException will not be thrown.


Full Program to Serialize Object and persisting EofIndicatorClass at EOF >
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.Serializable;
/*
* Class whose instance will be written at EOF during serialization
* to indicate EOF during deSerialization process.
*/
class EofIndicatorClass implements Serializable{}
/*Author : AnkitMittal  Copyright- contents must not be reproduced in any form*/
class Employee implements Serializable {
  
   private static final long serialVersionUID = 1L;
   private String name;
   public Employee(String name) {
          this.name = name;
   }
   @Override
   public String toString() {
          return "Employee [name=" + name + "]";
   }
}
/*
* Serialization class
*/
/** Copyright (c), AnkitMittal JavaMadeSoEasy.com */
public class SerializeEmployee {
   public static void main(String[] args) {
          Employee object1 = new Employee( "amy");
          Employee object2 = new Employee( "ankit");
          try {
                 OutputStream fout = new FileOutputStream("ser.txt");
                 ObjectOutput oout = new ObjectOutputStream(fout);
                 System.out.println("Serialization process has started, "
                              + "serializing employee objects...");
                 oout.writeObject(object1);
                 oout.writeObject(object2);
                
                 //write instance of EofIndicatorClass at EOF
                 oout.writeObject(new EofIndicatorClass());
                 oout.close();
                 System.out.println("Object Serialization completed.");
                
          } catch (IOException ioe) {
                 ioe.printStackTrace();
          }
   }
}
/*OUTPUT
Serialization process has started, serializing employee objects...
Object Serialization completed.
*/



Full Program to DeSerialize object and detecting EOF without throwing EOFException >
Avoid ObjectInputStream.readObject() from throwing EOFException at End Of File in java
import java.io.EOFException;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
/** Copyright (c), AnkitMittal JavaMadeSoEasy.com */
public class DeSerializeEmployee {
   public static void main(String[] args) {
          InputStream fin;
          try {
                 fin = new FileInputStream("ser.txt");
                 ObjectInput oin = new ObjectInputStream(fin);
                 System.out.println("DeSerialization process has started, "
                              + "displaying employee objects...");
                  /*
                 *If oin.readObject() returns instanceof EofIndicatorClass that means
                 *it's EOF, exit while loop and EOFException will not be thrown.
                 */
                Object obj;
                while(!((obj =  oin.readObject()) instanceof EofIndicatorClass)){
                     System.out.println(obj);
                }
                  oin.close();
          } catch (EOFException e) {
                 System.out.println("File ended");
          }  catch (FileNotFoundException e) {
                 e.printStackTrace();
          } catch (IOException e) {
                 e.printStackTrace();
          } catch (ClassNotFoundException e) {
                 e.printStackTrace();
          }
          System.out.println("Object DeSerialization completed.");
   }
}
/*OUTPUT
DeSerialization process has started, displaying employee objects...
Employee [name=amy]
Employee [name=ankit]
Object DeSerialization completed.
*/

If you note output of program EOFException wasn’t thrown, you may compare output of the program with DeSerialization done in this post where EOFException was thrown.


RELATED LINKS>

Serialization And Deserialization Tutorial


Serializing & DeSerializing >


Exceptions Tutorial in java in detail with diagrams and programs


No comments:

Post a Comment