Why EOFException occurs and how to avoid it in java


Contents of page >

  • How to avoid EOFException in java?

    • 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.
    • Solution 2) I’ll recommend you this solution, probably the best solution
      • Create a class EofIndicatorClass which implements Serializable interface.


What is hierarchy of java.lang. EOFException?

-java.lang.Object
-java.lang.Throwable
 -java.lang.Exception
  -java.lang.IOException
   -java.lang.EOFException

EOFException is Checked (compile time exceptions) and UnChecked (RuntimeExceptions) in java ?

java.lang.EOFException is a Checked (compile time) Exception in java.



What is EOFException in java?

EOFException is the End of file Exception. Many input streams through EOFException to indicate end of file (Few Java Api doesn’t provide any elegant solution to signify end the file). EOFException could be thrown >
  1. During DESERIALIZATION of object (when we are reading object using input stream).
  2. During use of RandomAccessFile, by using seek method we can move to random position, if seek is set beyond the length the file and we try to read from there than java.io.EOFException is thrown.

Now let’s discuss above two points with program and examples.


Example/Programs/Scenarios where EOFException may be thrown in java>


SERIALIZATION>
Create object of ObjectOutput and give its reference variable name oout and call writeObject() method and pass our employee object as parameter [oout.writeObject(object1) ]


OutputStream fout = new FileOutputStream("ser.txt");
ObjectOutput oout = new ObjectOutputStream(fout);
System.out.println("Serialization process has started, serializing employee objects...");
oout.writeObject(object1);


Program to Serialize Object>
package SerDeser1;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.Serializable;

/** Copyright (c), AnkitMittal JavaMadeSoEasy.com */

/*Author : AnkitMittal  Copyright- contents must not be reproduced in any form*/
class Employee implements Serializable {
  
   private static final long serialVersionUID = 1L;
   private Integer id;
   private String name;
   public Employee(Integer id, String name) {
          this.id = id;
          this.name = name;
   }
   @Override
   public String toString() {
          return "Employee [id=" + id + ", name=" + name + "]";
   }
}
public class SerializeEmployee {
   public static void main(String[] args) {
          Employee object1 = new Employee(1, "amy");
          Employee object2 = new Employee(2, "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);
                   oout.close();
                 System.out.println("Object Serialization completed.");
                
          } catch (IOException ioe) {
                 ioe.printStackTrace();
          }
   }
}
/*OUTPUT
Serialization process has started, serializing employee objects...
Object Serialization completed.
*/



DESERIALIZATION>
Create object of ObjectInput and give it’s reference variable name oin and call readObject() method [oin.readObject() ]

InputStream fin=new FileInputStream("ser.txt");
ObjectInput oin=new ObjectInputStream(fin);
System.out.println("DeSerialization process has started, displaying employee objects...");
Employee emp;
emp=(Employee)oin.readObject();


Program to DeSerialize object>
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 */
/*Author : AnkitMittal  Copyright- contents must not be reproduced in any form*/
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...");
                 Employee emp;
                 while ((emp = (Employee) oin.readObject()) != null) {
                       System.out.println(emp);
                 }
                 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 [id=1, name=amy]
Employee [id=2, name=ankit]
File ended
Object DeSerialization completed.
*/

In the above program when file is read till end using readObject() in while loop then EOFException is thrown. Java Api doesn’t provide any elegant solution to signify end the file.




By using seek method we can move to random position, if seek is set beyond the length the file and we try to read from there than java.io.EOFException is thrown.


Program to read/write from file using RandomAccessFile >
Note : Before executing below program, remove everything from c:/myFile.txt for better understanding of program
Or preferably you may delete this file because if file doesn't exist than RandomAccessFile will create new file.
import java.io.IOException;
import java.io.RandomAccessFile;
public class RandomAccessFileTest {
public static void main(String[] args) {
     try {
          String fileName = "c:/myFile.txt";
          String data = "abcdef";
          RandomAccessFile randomAccessFile;
         
          // ---- Writing in file using RandomAccessFile ----
          // 'rw' means opening file in Read-Write mode
          randomAccessFile = new RandomAccessFile(fileName, "rw");
          randomAccessFile.seek(5);
          randomAccessFile.writeUTF(data);
          System.out.println("Data written in "+" = "+data);
          randomAccessFile.close();
          // ---- Reading from file using RandomAccessFile ----
          // 'r' means opening file in Read mode
          randomAccessFile = new RandomAccessFile(fileName, "r");
          randomAccessFile.seek(5);
          data = randomAccessFile.readUTF();
          System.out.println("Data read from file = "+data);
          randomAccessFile.close();
     } catch (IOException e) {
          e.printStackTrace();
     }
}
}
/*
Data written in file = abcdef
Data read from file = abcdef
*/


After executing above program c:/myFile.txt will look like this >




How to avoid EOFException 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, let's discuss best possible solution to address the EOFException >
  • 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.

Now, let’s discuss solution 2 in detail.
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.
*/



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.




Summary >
So in this Exception handling java tutorial we learned what is hierarchy of java.lang. EOFException? java.lang.EOFException is a Checked (compile time) Exception in java. What is EOFException in java? Example/Programs/Scenarios where EOFException may be thrown in java. How to avoid EOFException in java?

Having any doubt? or you you liked the tutorial! Please comment in below section.
Please express your love by liking JavaMadeSoEasy.com (JMSE) on facebook, following on google+ or Twitter.


RELATED LINKS>

Most common and frequently occurring checked (compile time) and Errors in java >


Most common and frequently occurring unchecked (runtime) in java.


Most common and frequently occurring Errors in java >


Few More >




No comments:

Post a Comment