What is the process used to convert an object to a stream of bytes that can be saved to a file?

Serialization is the process of converting Java objects into a stream of bytes. The stream of bytes can be transmitted through a network connection, stored in a database as a BLOB object or saved as a binary file. The stored or transmitted stream of bytes can be reconstructed to Java object later. This article explains Serialization in Java, using a simple step by step example.

Note: The sample codes provided in this tutorial, use try-with-resources blocks to auto close the input and output streams. You need Java 7 or latest version to compile and run these codes. For more information about try-with-resources, visit to this tutorial: Try With Resources

Create a Student class with the attributes name, and age.

public class Student {     private String name;     private int age;     public String getName() {         return name;     }     public void setName(String name) {         this.name = name;     }     public void setAge(int age) {         this.age = age;     }     public int getAge() {         return age;     } }

Create a Main class as shown below, to create an object of Student.

public class Main {     public static void main(String[] args) {         Student stu = createStudent();         System.out.println("Name: " + stu.getName());         System.out.println("Age: " + stu.getAge());     }     /**      * Create a sample Student object.      *      * @return a Student object.      */     public static Student createStudent() {         // Create a Student object         Student stu = new Student();         stu.setName("Alice");         stu.setAge(24);         return stu;     } }

As defined earlier, serialization is the process of converting an object to a stream of bytes. Don't be afraid. The term stream of bytes refers just an array of bytes. To serialize the Student object, add a new method toStream to the Main class.

/**  * Convert a Student object into stream of bytes.  *  * @param stu  *            Student object.  * @return stream of bytes  */ public static byte[] toStream(Student stu) {     // Reference for stream of bytes     byte[] stream = null;     // ObjectOutputStream is used to convert a Java object into OutputStream     try (ByteArrayOutputStream baos = new ByteArrayOutputStream();             ObjectOutputStream oos = new ObjectOutputStream(baos);) {         oos.writeObject(stu);         stream = baos.toByteArray();     } catch (IOException e) {         // Error in serialization         e.printStackTrace();     }     return stream; }

The Main class with toStream method is provided here:

import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectOutputStream; import java.util.Arrays; public class Main {     public static void main(String[] args) {         Student stu = createStudent();         System.out.println("Name: " + stu.getName());         System.out.println("Age: " + stu.getAge());         // Convert the object to stream         byte[] stream = toStream(stu);         // Print the array         System.out.println(Arrays.toString(stream));     }     /**      * Create a sample Student object.      *      * @return a Student object.      */     public static Student createStudent() {         // Create a Student object         Student stu = new Student();         stu.setName("Alice");         stu.setAge(24);         return stu;     }     /**      * Convert a Student object into stream of bytes.      *      * @param stu      *            Student object.      * @return stream of bytes      */     public static byte[] toStream(Student stu) {         // Reference for stream of bytes         byte[] stream = null;         // ObjectOutputStream is used to convert a Java object into OutputStream         try (ByteArrayOutputStream baos = new ByteArrayOutputStream();                 ObjectOutputStream oos = new ObjectOutputStream(baos);) {             oos.writeObject(stu);             stream = baos.toByteArray();         } catch (IOException e) {             // Error in serialization             e.printStackTrace();         }         return stream;     } }

If you run this modified code, you will end up with java.io.NotSerializableException. The reason is: to convert any objects of a class into a stream, a special permission has to be provided for that class. Rather than defining it as a permission. In Java, this permission is provided by implementing the interface java.io.Serializable. This interface does not have any abstract methods. Purpose of this interface is just indicating that, the object of this classes are allowed to convert into a stream of bytes.

Even though, there are no methods to override, it is the best practice to add a long variable serialVersionUID to the Serializable class. This id is used to identify the exact class of byte stream, when the stream is converted back to the Java object. The serialVersionUID can be any long number.

import java.io.Serializable; /**  * Student class  *  * @author gobinath  *  */ public class Student implements Serializable {     // Serial version ID – Just a random number     private static final long serialVersionUID = 5230549922091722630L;     private String name;     private int age;     public String getName() {         return name;     }     public void setName(String name) {         this.name = name;     }     public void setAge(int age) {         this.age = age;     }     public int getAge() {         return age;     } }

Now run the code again and test the output. Fine! we have converted a Student object into an array of bytes. What about converting the byte array back to Student object?

Add a new method toStudent in the Main class. This method converts the given array of bytes to a Student object.

/**  * Convert stream of bytes to Student.  *  * @param stream  *            byte array  * @return Student object  */ public static Student toStudent(byte[] stream) {     Student stu = null;     try (ByteArrayInputStream bais = new ByteArrayInputStream(stream);             ObjectInputStream ois = new ObjectInputStream(bais);) {         stu = (Student) ois.readObject();     } catch (IOException e) {         // Error in de-serialization         e.printStackTrace();     } catch (ClassNotFoundException e) {         // You are converting an invalid stream to Student         e.printStackTrace();     }     return stu; }

Modify the Main class as shown below and test the output.

import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.util.Arrays; public class Main {     public static void main(String[] args) {         Student stu = createStudent();         System.out.println("Name: " + stu.getName());         System.out.println("Age: " + stu.getAge());         // Convert the object to stream         byte[] stream = toStream(stu);         // Print the array         System.out.println(Arrays.toString(stream));         Student convertedStu = toStudent(stream);         System.out.println("Name: " + convertedStu.getName());         System.out.println("Age: " + convertedStu.getAge());     }     /**      * Create a sample Student object.      *      * @return a Student object.      */     public static Student createStudent() {         // Create a Student object         Student stu = new Student();         stu.setName("Alice");         stu.setAge(24);         return stu;     }     /**      * Convert a Student object into stream of bytes.      *      * @param stu      *            Student object.      * @return stream of bytes      */     public static byte[] toStream(Student stu) {         // Reference for stream of bytes         byte[] stream = null;         // ObjectOutputStream is used to convert a Java object into OutputStream         try (ByteArrayOutputStream baos = new ByteArrayOutputStream();                 ObjectOutputStream oos = new ObjectOutputStream(baos);) {             oos.writeObject(stu);             stream = baos.toByteArray();         } catch (IOException e) {             // Error in serialization             e.printStackTrace();         }         return stream;     }     /**      * Convert stream of bytes to Student.      *      * @param stream      *            byte array      * @return Student object      */     public static Student toStudent(byte[] stream) {         Student stu = null;         try (ByteArrayInputStream bais = new ByteArrayInputStream(stream);                 ObjectInputStream ois = new ObjectInputStream(bais);) {             stu = (Student) ois.readObject();         } catch (IOException e) {             // Error in de-serialization             e.printStackTrace();         } catch (ClassNotFoundException e) {             // You are converting an invalid stream to Student             e.printStackTrace();         }         return stu;     } }

The above code serializes a Student object to a stream of bytes, and deserailizes it back to the Student object. Let's use serialization to save a Student object to a file and read it back later.

Create the save method and call this method from the main method as shown below. Remember to change the file location based on your operating system.

import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectOutputStream; public class Main {     public static void main(String[] args) {         Student stu = createStudent();         System.out.println("Name: " + stu.getName());         System.out.println("Age: " + stu.getAge());         // Give any filename         save(stu, "/home/gobinath/student.xxx");     }     /**      * Create a sample Student object.      *      * @return a Student object.      */     public static Student createStudent() {         // Create a Student object         Student stu = new Student();         stu.setName("Alice");         stu.setAge(24);         return stu;     }     /**      * Save a student into a file using Serialization.      *      * @param stu      *            the Student to save.      * @param fileName      *            the location to save.      */     public static void save(Student stu, String fileName) {         try (FileOutputStream fos = new FileOutputStream(fileName);                 ObjectOutputStream oos = new ObjectOutputStream(fos);) {             oos.writeObject(stu);         } catch (FileNotFoundException e) {             // Error in accessing the file             e.printStackTrace();         } catch (IOException e) {             // Error in converting the Student             e.printStackTrace();         }     } }

After executing this code, go and check whether the file is created or not. If you do not have any permission issues for the given valid location, the file must be created at the provided location.

To read the Student object, add a new method read as shown below and call it from the main method.

import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; public class Main {     public static void main(String[] args) {         Student stu = createStudent();         System.out.println("Name: " + stu.getName());         System.out.println("Age: " + stu.getAge());         // Give any filename         save(stu, "/home/gobinath/student.xxx");         // Provide the file name of your serialized object         Student newStu = read("/home/gobinath/student.xxx");         System.out.println("Name: " + newStu.getName());         System.out.println("Age: " + newStu.getAge());     }     /**      * Create a sample Student object.      *      * @return a Student object.      */     public static Student createStudent() {         // Create a Student object         Student stu = new Student();         stu.setName("Alice");         stu.setAge(24);         return stu;     }     /**      * Save a student into a file using Serialization.      *      * @param stu      *            the Student to save.      * @param fileName      *            the location to save.      */     public static void save(Student stu, String fileName) {         try (FileOutputStream fos = new FileOutputStream(fileName);                 ObjectOutputStream oos = new ObjectOutputStream(fos);) {             oos.writeObject(stu);         } catch (FileNotFoundException e) {             // Error in accessing the file             e.printStackTrace();         } catch (IOException e) {             // Error in converting the Student             e.printStackTrace();         }     }     /**      * Reading Student object from the given file.      *      * @param fileName      *            location of the file.      * @return converted Student object.      */     public static Student read(String fileName) {         Student stu = null;         try (FileInputStream fis = new FileInputStream(fileName); ObjectInputStream ois = new ObjectInputStream(fis);) {             stu = (Student) ois.readObject();         } catch (FileNotFoundException e) {             // Error in accessing the file             e.printStackTrace();         } catch (IOException e) {             // Error in converting the Student             e.printStackTrace();         } catch (ClassNotFoundException e) {             // You are converting an invalid stream to Student             e.printStackTrace();         }         return stu;     } }

This code will read and print the saved student's name Alice, and her age 24.

Seems to be good. But what will be the output, if the saved object is read after more than one years? Regardless of number of years, the age will be displayed as 24 forever. A possible trick to overcome this problem is: rather than saving the age, save the birth year to the stream of bytes and redefine the age when deserailize the student back. To ignore the serialization of a property, declare the property as a transient property. Modify the int age as transient int age and run the code.

import java.io.Serializable; /**  * Student class  *  * @author gobinath  *  */ public class Student implements Serializable {     // Serial version ID – Just a random number     private static final long serialVersionUID = 5230549922091722630L;     private String name;     private transient int age;     public String getName() {         return name;     }     public void setName(String name) {         this.name = name;     }     public void setAge(int age) {         this.age = age;     }     public int getAge() {         return age;     } }

This time the deserialized student's age will be 0. This is because of the transient modifier. If the age is not available during deserialization, Java will assign the default value of that data type (For int, default value is 0).

To save the birth year, add the following method into the Student class.

/**  * This method is called during serialization.  *  * @param oos  */ private void writeObject(ObjectOutputStream oos) {     // Create a calendar object of current date     Calendar current = Calendar.getInstance();     // Get the current year     int currentYear = current.get(Calendar.YEAR);     // Calculate the birth year     int birthYear = currentYear - age;     try {         // Write the default attributes first         oos.defaultWriteObject();         // Write the birth year         oos.writeInt(birthYear);     } catch (IOException e) {         e.printStackTrace();     } }

The writeObject method is called by Java, when the object is serialized to stream of bytes.

To restore the age, add the following method into the Student class.

/**  * This method is called during deserialization.  *  * @param ois  */ private void readObject(ObjectInputStream ois) {     // Create a calendar object of current date     Calendar current = Calendar.getInstance();     // Get the current year     int currentYear = current.get(Calendar.YEAR);     try {         // Read the default attributes first         ois.defaultReadObject();         // Read the birth year         int birthYear = ois.readInt();         // Calculate the age         this.age = currentYear - birthYear;     } catch (IOException e) {         e.printStackTrace();     } catch (ClassNotFoundException e) {         e.printStackTrace();     } }

The readObject method is called by Java, when a stream of byte is deserialized to Java object.

After the modification, your code should be something similar to this:

import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import java.util.Calendar; /**  * Student class  *  * @author gobinath  *  */ public class Student implements Serializable {     // Serial version ID     private static final long serialVersionUID = 5230549922091722630L;     private String name;     private transient int age;     public String getName() {         return name;     }     public void setName(String name) {         this.name = name;     }     public void setAge(int age) {         this.age = age;     }     public int getAge() {         return age;     }     /**      * This method is called during serialization.      *      * @param oos      */     private void writeObject(ObjectOutputStream oos) {         // Create a calendar object of current date         Calendar current = Calendar.getInstance();         // Get the current year         int currentYear = current.get(Calendar.YEAR);         // Calculate the birth year         int birthYear = currentYear - age;         try {             // Write the default attributes first             oos.defaultWriteObject();             // Write the birth year             oos.writeInt(birthYear);         } catch (IOException e) {             e.printStackTrace();         }     }     /**      * This method is called during deserialization.      *      * @param ois      */     private void readObject(ObjectInputStream ois) {         // Create a calendar object of current date         Calendar current = Calendar.getInstance();         // Get the current year         int currentYear = current.get(Calendar.YEAR);         try {             // Read the default attributes first             ois.defaultReadObject();             // Read the birth year             int birthYear = ois.readInt();             // Calculate the age             this.age = currentYear - birthYear;         } catch (IOException e) {             e.printStackTrace();         } catch (ClassNotFoundException e) {             e.printStackTrace();         }     } }

This time, output will be updated based on the current year.

Conclusively serialization is the process of converting an object into stream of bytes. The converted byte stream can be used for multiple purposes. Java has a marker interface (an interface without any methods) Serializable to flag the classes, that their objects are allowed to undergo the serialization. writeObject and readObject methods are used to perform advanced operations during serialization and deserialization.

Find the source codes at Git Hub.

What is the process used to convert an object to a stream of bytes that can be saved in a file?

Serialization is the process of converting an object into a stream of bytes to store the object or transmit it to memory, a database, or a file.

What is the process used to convert an object to a stream?

The process of converting object to stream is called serialization in java.

Is the process in which an object converts into a byte stream?

Serialization is the process of converting the state of an object into a byte stream.

How do you convert objects to bytes?

Write the contents of the object to the output stream using the writeObject() method of the ObjectOutputStream class. Flush the contents to the stream using the flush() method. Finally, convert the contents of the ByteArrayOutputStream to a byte array using the toByteArray() method.

Toplist

Neuester Beitrag

Stichworte