java:object_serialization

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Next revision
Previous revision
java:object_serialization [2017/02/17 13:22]
gthanos created
java:object_serialization [2017/02/17 14:11] (current)
gthanos
Line 1: Line 1:
-====== Object Serialization ======+====== Object Serialization/​Deserialization ​======
  
 Η Java παρέχει την δυνατότητα μετατροπής ενός αντικειμένου σε μία σειρά από bytes, προκειμένου αυτό στη συνέχεια να αποθηκευτεί σε ένα μέσω μόνιμης αποθήκευσης (π.χ. αρχείο στο filesystem) ή να μεταδοθεί μέσω δικτύου προκειμένου να δημιουργηθεί ένα αντίγραφο του σε απομακρυσμένο σημείο. Η διαδικασία μετατροπής των αντικειμένων σε bytes ονομάζεται **object serialization**. Η Java παρέχει την δυνατότητα μετατροπής ενός αντικειμένου σε μία σειρά από bytes, προκειμένου αυτό στη συνέχεια να αποθηκευτεί σε ένα μέσω μόνιμης αποθήκευσης (π.χ. αρχείο στο filesystem) ή να μεταδοθεί μέσω δικτύου προκειμένου να δημιουργηθεί ένα αντίγραφο του σε απομακρυσμένο σημείο. Η διαδικασία μετατροπής των αντικειμένων σε bytes ονομάζεται **object serialization**.
Line 7: Line 7:
 Οι κλάσεις **[[http://​docs.oracle.com/​javase/​7/​docs/​api/​java/​io/​ObjectInputStream.html|ObjectInputStream]]** και **[[http://​docs.oracle.com/​javase/​7/​docs/​api/​java/​io/​ObjectOutputStream.html|ObjectOutputStream]]** αποτελούν κλάσεις τύπου **[[http://​docs.oracle.com/​javase/​7/​docs/​api/​java/​io/​InputStream.html|InputStream]]** και **[[http://​docs.oracle.com/​javase/​7/​docs/​api/​java/​io/​OutputStream.html|OutputStream]]** υψηλού επιπέδου οι οποίες επιτελούν την διαδικασία της "​σειριοποίησης"​ και "​αποσειριοποίησης"​ των αντικειμένων. Οι κλάσεις **[[http://​docs.oracle.com/​javase/​7/​docs/​api/​java/​io/​ObjectInputStream.html|ObjectInputStream]]** και **[[http://​docs.oracle.com/​javase/​7/​docs/​api/​java/​io/​ObjectOutputStream.html|ObjectOutputStream]]** αποτελούν κλάσεις τύπου **[[http://​docs.oracle.com/​javase/​7/​docs/​api/​java/​io/​InputStream.html|InputStream]]** και **[[http://​docs.oracle.com/​javase/​7/​docs/​api/​java/​io/​OutputStream.html|OutputStream]]** υψηλού επιπέδου οι οποίες επιτελούν την διαδικασία της "​σειριοποίησης"​ και "​αποσειριοποίησης"​ των αντικειμένων.
  
-Από τις μεθόδους της κλάσης **[[http://​docs.oracle.com/​javase/​7/​docs/​api/​java/​io/​ObjectOutputStream.html|ObjectOutputStream]]** μας ενδιαφέρει η μέθοδος [[http://​docs.oracle.com/​javase/​7/​docs/​api/​java/​io/​ObjectOutputStream.html#​writeObject(java.lang.Object)|writeObject]] η οποία ​περιγράφεται παρακάτω+Από τις μεθόδους της κλάσης **[[http://​docs.oracle.com/​javase/​7/​docs/​api/​java/​io/​ObjectOutputStream.html|ObjectOutputStream]]** μας ενδιαφέρει η μέθοδος [[http://​docs.oracle.com/​javase/​7/​docs/​api/​java/​io/​ObjectOutputStream.html#​writeObject(java.lang.Object)|writeObject]] η οποία ​μετατρέπει σε σειρά από bytes το αντικείμενο **obj**
 <code java> <code java>
 public final void writeObject(Object obj) throws IOException public final void writeObject(Object obj) throws IOException
Line 18: Line 18:
 </​code>​ </​code>​
  
-Αντίστοιχα από τις μεθόδους της κλάσης **[[http://​docs.oracle.com/​javase/​7/​docs/​api/​java/​io/​ObjectInputStream.html|ObjectInputStream]]** μας ενδιαφέρει η μέθοδο [[http://​docs.oracle.com/​javase/​7/​docs/​api/​java/​io/​ObjectInputStream.html#​readObject()|readObject]] ​+Αντίστοιχα από τις μεθόδους της κλάσης **[[http://​docs.oracle.com/​javase/​7/​docs/​api/​java/​io/​ObjectInputStream.html|ObjectInputStream]]** μας ενδιαφέρει η μέθοδος [[http://​docs.oracle.com/​javase/​7/​docs/​api/​java/​io/​ObjectInputStream.html#​readObject()|readObject]] ​η οποία μετατρέπει σε αντικείμενο μία σειρά από bytes.
  
 <code java> <code java>
Line 31: Line 31:
     IOException - Any of the usual Input/​Output related exceptions.     IOException - Any of the usual Input/​Output related exceptions.
 </​code>​ </​code>​
 +
 +Απαραίτητη προϋπόθεση για το serialization/​deserialization των αντικειμένων είναι ​
 +  - η κλάση του αντικειμένου να υλοποιεί το //​interface//​ **[[http://​docs.oracle.com/​javase/​7/​docs/​api/​java/​io/​Serializable.html|Serializable]]**.
 +  - όλα τα πεδία της κλάσης να υλοποιούν το //​interface//​ **[[http://​docs.oracle.com/​javase/​7/​docs/​api/​java/​io/​Serializable.html|Serializable]]**. Εάν υπάρχουν πεδία που δεν το υλοποιούν τότε αυτά θα πρέπει να δηλωθούν ως **transient**. Η δήλωση **transient** μπροστά από ένα πεδίο υποδεικνύει ότι αυτό δεν θα συμπεριληφθεί στη διαδικασία του serialization/​deserialization.
 +
 +Όλοι οι βασικοί (primitive) τύποι δεδομένων κατά την διαδικασία του serialization μετατρέπονται σε αναφορικούς τύπους. Οι αναφορικοί τύποι Integer, Long, Double, Float, Character, Boolean και String είναι όλοι τύποι δεδομένων που υποστηρίζουν serialization.
 +
 +===== Παράδειγμα Serialization =====
 +
 +Θα επιχειρήσουμε να κάνουμε serialize ένα αντικείμενο της παρακάτω κλάσης Employee.
 +<code java Employee.java>​
 +iimport java.util.*;​
 +
 +public class Employee implements java.io.Serializable {
 +   ​public String name;
 +   ​public String address;
 +   ​public int AMKA;
 +   ​public double salary;
 +   ​public Employee next;
 +   ​public ArrayList<​Employee>​ list;
 +   
 +   ​public String toString() {
 +      String str = "Name: " + name+"​\n";​
 +      str+="​Address:​ " + address+"​\n";​
 +      str+="​AMKA:​ " + AMKA+"​\n";​
 +      str+="​Salary:​ " + salary+"​\n";​
 +      if(next != null)
 +        str+="​Next:​ " + next.name+"​\n";​
 +      ​
 +      if( list != null) {
 +        Iterator<​Employee>​ it = list.iterator();​
 +        if( it.hasNext() ) {
 +          str+="​List:​ ";
 +        }
 +        while( it.hasNext() ) {
 +          str+= it.next().name+",​ ";
 +        }
 +        str+="​\n";​
 +      }
 +      return str;
 +   }
 +}
 +</​code>​
 +
 +Ας υποθέσουμε ότι κατασκευάζουμε δύο τέτοια αντικείμενα τα οποία τα μετατρέπουμε σε μία σειρά από bytes και τα αποθηκεύουμε στο αρχείο **employees.ser** (υποθέτουμε ότι έχετε την δυνατότητα να δημιουργήσετε το αρχείο στον τρέχοντα κατάλογο). Ο κώδικας μετατροπής και αποθήκευσης δίνεται παρακάτω:​
 +
 +<code java SerializeDemo.java>​
 +import java.io.*;
 +import java.util.*;​
 +public class SerializeDemo {
 +
 +   ​public static void main(String [] args) {
 +      Employee e = new Employee();
 +      e.name = "Vana Doufexi";​
 +      e.address = "​Gklavani 37, Volos";​
 +      e.AMKA = 11122333;
 +      e.salary = 1000.9999;
 +      ​
 +      Employee e1 = new Employee();
 +      e1.name = "​George Thanos";​
 +      e1.address = "28hs Septembriou & Glavani, Volos";​
 +      e1.AMKA = 11122999;
 +      e1.salary = 458.1234;
 +      ​
 +      e.next = e1;
 +      e1.next = e;
 +      ​
 +      e.list = new ArrayList<>​();​
 +      e.list.add(e);​
 +      e.list.add(e1);​
 +      ​
 +      e1.list = new ArrayList<>​();​
 +      e1.list.add(e);​
 +      e1.list.add(e1);​
 +      ​
 +      try {
 +         ​FileOutputStream fileOut =
 +         new FileOutputStream("​./​employees.ser"​);​
 +         ​ObjectOutputStream out = new ObjectOutputStream(fileOut);​
 +         ​out.writeObject(e);​
 +         ​out.writeObject(e1);​
 +         ​out.close();​
 +         ​fileOut.close();​
 +         ​System.out.printf("​Serialized data is saved in /​tmp/​employee.ser"​);​
 +      }catch(IOException ex) {
 +         ​ex.printStackTrace();​
 +      }
 +   }
 +}
 +</​code>​
 +
 +Μεταγλωττίστε και τρέξτε το πρόγραμμα και επιβεβαιώστε ότι δημιουργήθηκε το αρχείο **employees.ser**.
 +
 +===== Παράδειγμα Deserialization =====
 +
 +Ας υποθέσουμε ότι αφού αποθηκεύσαμε τα αντικείμενα στο αρχείο **employees.ser** θέλουμε να τα ανακτήσουμε ως λειτουργικά αντικείμενα σε ένα νέο πρόγραμμα. Ας δούμε το πρόγραμμα αυτό, το οποίο εκτυπώνει το περιεχόμενο τους με την βοήθεια της μεθόδου toString().
 +
 +<code java DeserializeDemo.java>​
 +import java.io.*;
 +public class DeserializeDemo {
 +
 +   ​public static void main(String [] args) {
 +      Employee e, e1;
 +      try {
 +         ​FileInputStream fileIn = new FileInputStream("​employees.ser"​);​
 +         ​ObjectInputStream in = new ObjectInputStream(fileIn);​
 +         e = (Employee) in.readObject();​
 +         e1 = (Employee) in.readObject();​
 +         ​in.close();​
 +         ​fileIn.close();​
 +      }catch(IOException i) {
 +         ​i.printStackTrace();​
 +         ​return;​
 +      }catch(ClassNotFoundException ex) {
 +         ​System.out.println("​Employee class not found"​);​
 +         ​ex.printStackTrace();​
 +         ​return;​
 +      }
 +      ​
 +      System.out.println(e);​
 +      System.out.println(e1); ​     ​
 +   }
 +}
 +</​code>​
 +
 +<WRAP todo 80% center round>
 +Στο παραπάνω παράδειγμα δηλώστε τα τελευταία τρία πεδία της κλάσης Employee ως transient, oπως παρακάτω. Μεταγλωττίστε και τρέξτε ξανά τις κλάσεις **SerializeDemo** και **DeserializeDemo**. Τι παρατηρείτε;​
 +</​WRAP>​
 +
 +<code java Employee.java>​
 +import java.util.*;​
 +
 +public class Employee implements java.io.Serializable {
 +   ​public String name;
 +   ​public String address;
 +   ​public int AMKA;
 +   ​public transient double salary;
 +   ​public transient Employee next;
 +   ​public transient ArrayList<​Employee>​ list;
 +   
 +   ​public String toString() {
 +      String str = "Name: " + name+"​\n";​
 +      str+="​Address:​ " + address+"​\n";​
 +      str+="​AMKA:​ " + AMKA+"​\n";​
 +      str+="​Salary:​ " + salary+"​\n";​
 +      if(next != null)
 +        str+="​Next:​ " + next.name+"​\n";​
 +      ​
 +      if( list != null) {
 +        Iterator<​Employee>​ it = list.iterator();​
 +        if( it.hasNext() ) {
 +          str+="​List:​ ";
 +        }
 +        while( it.hasNext() ) {
 +          str+= it.next().name+",​ ";
 +        }
 +        str+="​\n";​
 +      }
 +      return str;
 +   }
 +}
 +</​code>​
 +
 +
 +|Προηγούμενο:​ [[ :​java:​write_to_file | Γράφοντας σε αρχείο ]] | [[ :toc | Περιεχόμενα ]] | Επόμενο:​ [[ :​java:​generics | Παραμετρικοί τύποι δεδομένων ]] |
  
  
java/object_serialization.1487337759.txt.gz · Last modified: 2017/02/17 13:22 by gthanos