JavaData & JavaFile Handling in Java: Object Serialization

File Handling in Java: Object Serialization

Developer.com content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More.

Object serialization is a mechanism to manipulate Java objects (POJO) to and from a stream of bytes. Serialization, in particular, refers to its representation as a sequence of bytes. These bytes contains an object’s data, type information of the object, and also the type of data content in the object. An object, once serialized, can be persisted in a file or used in an application that communicate via network. The reverse process, called deserialization, is used to re-create the same object in memory from the stream of bytes. Data communication via objects rather than a sequence of bytes is convenient and efficient in both file handling and network communication. In this article, we shall explore the serialization/deserialization process with the help of a file handling mechanism. Conceptually, serialization in network programming also follows the same idea.

The Need for Objects to be Serialized

Because serialization converts an object to a stream of bytes and deserialization re-creates the object in memory, the basic idea of operation remains the same as it in object persistence or a network transfer. Note that serialization is not the only answer to transform objects into a stream of bytes but a standard and convenient way to do so. Otherwise, one had to re-create objects from the sequence of bytes from scratch in every application. For example, in a simple file handling program without serialization, when an instance variable for a certain object were to output to a disk file, the type information of object data gets lost. That means, a value, say “55,” is read back from a file, there is no way to tell if the value came from a Integer, a String, or a Double. Also, it is not possible to determine whether the separator used in the file between values is a space character or something else. Are there single records in a line or multiple records per line in the file? This information is necessary for re-creating the object, especially by the program that reads the data. If, however, the program knows the object type exactly, perhaps it’s all right and possible to read into the correct object. But in practice, it’s often not so. It is not possible to know precisely how data is stored in a file unless type information of the object with its content are also maintained systematically in the file.

Implementing Object Serialization

Serialization of a object starts with implementing a java.io.Serialization interface. Then, to work with the serialized object, we have to initialize the ObjectInputStream and ObjectOutputStream objects with stream objects. ObjectInputStream implements the ObjectInput interface and ObjectOutputStream implements the ObjectOutput interface, respectively. These objects read from and write to file stream objects, such as FileInputStream and FileOutputStream, respectively (in case of file handling). Both file stream and object streams are basically stream objects wrapped into one another for the purpose of object persistence in a file. The stream object being created wraps another stream object specified as a constructor argument; for example, to wrap FileOuputStream in an ObjectOutputStream, we pass a FileOutputStream object to the ObjectOutputStream‘s constructor. The method writeObject, responsible for streaming object bytes, takes an object that implements a Serializable interface as an argument. In a way, an object that implements a Serializable interface is tagged to transform into a sequence of bytes retaining not only the object values but also the type information of the object and its content as well. Serialization acts as a tagging interface and does not have any method of its own. ObjectInputStream/ObjectOuputStream will not input/output an object unless it is marked serializable. A serializable class must ensure that the instance variables of the class must also be serializable; if this is not so, they must be declared as transient to indicate non serializability and they should be ignored during the serializability process. This situation occurs in cases such as in serializing reference types. All primitive types of variables in Java are serializable including array objects. However, for some reference types or an array of reference types, it may occur that the referred object is not serializable.

Object Serialization in a Sequential Access File

Let us create and manipulate a simple sequential access file using object serialization to delineate the idea further.

This is our serialized POJO implementing a java.io.Serializable interface.

public class ProductRecord implements Serializable{
   private int productCode;
   private String composition;
   private String productName;
   private String company;
   private int stockQuantity;
   private int reorderLevel;
   private float unitPrice;

   // ...constructors, getters,and setters
}

This class shows how to implement ObjectInputStream and ObjectOutputStream objects to read and write a serialized object into a file. The method writeToFile/readFromFile implements the file input/output mechanism from a stream of bytes transformed by ObjectOutputStream/ObjectInputStream.

public class ProductFileStream {

   public void writeToFile(List<ProductRecord> list, String file) {
      ObjectOutputStream outStream = null;
      try {
         outStream = new ObjectOutputStream(new FileOutputStream(file));
         for (ProductRecord p : list) {
            outStream.writeObject(p);
         }

      } catch (IOException ioException) {
         System.err.println("Error opening file.");
      } catch (NoSuchElementException noSuchElementException) {
         System.err.println("Invalid input.");
      } finally {
         try {
            if (outStream != null)
               outStream.close();
         } catch (IOException ioException) {
            System.err.println("Error closing file.");
         }
      }
   }

   public List<ProductRecord> readFromFile(String file) {
      List<ProductRecord> list = new ArrayList<>();
      ObjectInputStream inputStream = null;
      try {
         inputStream = new ObjectInputStream(new FileInputStream(file));
         while (true) {
            ProductRecord p = (ProductRecord) inputStream.readObject();
            list.add(p);
         }
      } catch (EOFException eofException) {
         return list;
      } catch (ClassNotFoundException classNotFoundException) {
         System.err.println("Object creation failed.");
      } catch (IOException ioException) {
         System.err.println("Error opening file.");
      } finally {
         try {
            if (inputStream != null)
               inputStream.close();
         } catch (IOException ioException) {
            System.err.println("Error closing file.");
         }
      }
      return list;
   }

}

Testing object serialization in a file with dummy data:

public class ProductFile{
public static void main(String[] args) {
   String filePath = "/home/mano/temp/product.dat";
   List<ProductRecord> list = new ArrayList<>();
   list.add(new ProductRecord(111, "Amitryptyline", "Amiline", "Torrent",
      10, 5, 13.35f));
   // ...dummy data

   list.add(new ProductRecord(191, "Amlodipine", "Amdepin",
      "ZydusCadila", 18, 6, 20.90f));
   ProductFileStream pf=new ProductFileStream();
   pf.writeToFile(list, filePath);
   List<ProductRecord> products=pf.readFromFile(filePath);
   printlist(products);

}

public static void printlist(List<ProductRecord> list) {
   System.out.printf("%-7s%-20s%-20s%-20s%-10s%-10s%-10sn", "Code",
      "Generic", "Name", "Company", "Stock", "Reorder", "Unit Price");
   for (ProductRecord p : list) {
      System.out.printf("%-7d%-20s%-20s%-20s%-10d%-10d%.2fn",
      p.getProductCode(), p.getComposition(), p.getProductName(),
      p.getCompany(), p.getStockQuantity(), p.getReorderLevel(),
      p.getUnitPrice());
      }
   }
}

Conclusion

The core idea of serialization is to transform an object into a stream of bytes and deserialization is to re-create the object back from the stream of bytes; that’s it! Java provides a standard mechanism to achieve it through java.io.Serialization. File handling and Network programs are the most common but not the only example that require such a mechanism. Storing images or image processing is also another area where serialization may come in handy. Try your hand at it and explore its power in different area of programming. Serialization in Network programming is an interesting area. Do comment if you are inquisitive; together, we’ll explore it.

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Latest Posts

Related Stories