next up previous contents index
Next: 22 Compression des données Up: Java: Le langage Previous: 20 Threads

Subsections

21 Serialization

   

21.1 Lire et écrire des objets

       

21.1.1 Introduction

Le concept de Object Serialization a été introduit à partir de version 1.1. et caractérisé le fait de pouvoir lire ou d'écrire des objets (instance d'une classe). Il ne s'agit pas, lorsqu'il s'agit d'écrire un objet, de donner une représentation textuelle d'un objet, mais de donner une représentation binaire. Cette représentation sera évidemment indépendante de la plateforme utilisée.

L'intérêt de pouvoir donner une représentation binaire d'un objet est partciulièrement utile dans les cas suivants:

L'écriture d'un objet est relativement simple; par exemple, l'exemple suivant permet d'écrire l'état d'un objet dans un fichier :

 
FileOutputStream sortie = new FileOutputStream("resultat");
ObjectOutputStream s = new ObjectOutputStream(sortie);
s.writeObject(new Date());
s.flush();

La méthode writeObject de la classe ObjectOutputStream écrit de manière récursive toutes les structures de données de classe Date que nous avons vu au chapitre 6.

C'est évidemment au concepteur de la classe, dont est issu l'objet que l'on désire écrire, qu'il appartient de permettre ou non l'écriture d'un objet[*]. La classe ObjectOutputStream implante l'interface DataOutput qui permet d'écrire des données primitives grâce aux méthodes writeInt, writeFloat, etc. Par contre pour les objets, le concepteur de la classe devra préciser qu'il accepte de permettre l'écriture avec la méthode writeObject pour ses instances.

Pour ce faire, Java définit une interface Serializable. Ainsi, un objet ne sera écrit par la méthode writeObject que si la classe à laquelle elle appartient implante cette interface.

De même, la lecture d'un objet devrait correspondre à :

 
FileInputStream entree = new FileInputStream("resultat");
ObjectInputStream s = new ObjectInputStream(in);
Date date = (Date)s.readObject();
On aura compris que, comme pour l'écriture, à travers l'interface Serializable, le concepteur de la classe Date devra fournir la méthode readObject[*].

21.1.2 ObjectInputStream

 

   public class ObjectInputStream extends InputStream implements ObjectInput, ObjectStreamConstants {
      public ObjectInputStream(InputStream in) throws StreamCorruptedException, IOException;
      public final Object readObject() throws OptionalDataException, ClassNotFoundException, IOException;
      public void defaultReadObject() throws IOException, ClassNotFoundException, NotActiveException;
      public GetField readFields() throws IOException;
      public synchronized void registerValidation(ObjectInputValidation obj, int prio) throws NotActiveException, InvalidObjectException;
      protected Class resolveClass(ObjectStreamClass v) throws IOException, ClassNotFoundException;
      protected Object resolveObject(Object obj) throws IOException;
      protected boolean enableResolveObject(boolean enable) throws SecurityException;
      protected void readStreamHeader() throws IOException, StreamCorruptedException;
      public int read() throws IOException;
      public int read(byte[] data, int offset, int length) throws IOException
      public int available() throws IOException;
      public void close() throws IOException;
      public boolean readBoolean() throws IOException;
      public byte readByte() throws IOException;
      public int readUnsignedByte() throws IOException;
      public short readShort() throws IOException;
      public int readUnsignedShort() throws IOException;
      public char readChar() throws IOException;
      public int readInt() throws IOException;
      public long readLong() throws IOException;
      public float readFloat() throws IOException;
      public double readDouble() throws IOException;
      public void readFully(byte[] data) throws IOException;
      public void readFully(byte[] data, int offset, int size) throws IOException;
      public int skipBytes(int len) throws IOException;
      public String readLine() throws IOException;
      public String readUTF() throws IOException;

      // Class to provide access to serializable fields.
      static abstract public class GetField {
         public ObjectStreamClass getObjectStreamClass();
         public boolean defaulted(String name) throws IOException, IllegalArgumentException;
         public char get(String name, char default) throws IOException, IllegalArgumentException;
         public boolean get(String name, boolean default) throws IOException, IllegalArgumentException;
         public byte get(String name, byte default) throws IOException, IllegalArgumentException;
         public short get(String name, short default) throws IOException, IllegalArgumentException;
         public int get(String name, int default) throws IOException, IllegalArgumentException;
         public long get(String name, long default) throws IOException, IllegalArgumentException;
         public float get(String name, float default) throws IOException, IllegalArgumentException;
         public double get(String name, double default) throws IOException, IllegalArgumentException;
         public Object get(String name, Object default) throws IOException, IllegalArgumentException;
      }

      protected ObjectInputStream() throws StreamCorruptedException, IOException;
      protected readObjectOverride() throws OptionalDataException, ClassNotFoundException, IOException;
   }

21.1.3 ObjectOutputStream

 

   public class ObjectOutputStream extends OutputStream implements ObjectOutput, ObjectStreamConstants{
      public ObjectOutputStream(OutputStream out) throws IOException;
      public final void writeObject(Object obj) throws IOException;
      public void defaultWriteObject() throws IOException, NotActiveException;
      public PutField putFields() throws IOException;
      public writeFields() throws IOException;
      public void reset() throws IOException;
      protected void annotateClass(Class cl) throws IOException;
      protected Object replaceObject(Object obj) throws IOException;
      protected boolean enableReplaceObject(boolean enable) throws SecurityException;
      protected void writeStreamHeader() throws IOException;
      public void write(int data) throws IOException;
      public void write(byte b[]) throws IOException;
      public void write(byte b[], int off, int len) throws IOException;
      public void flush() throws IOException;
      protected void drain() throws IOException;
      public void close() throws IOException;
      public void writeBoolean(boolean data) throws IOException;
      public void writeByte(int data) throws IOException;
      public void writeShort(int data) throws IOException;
      public void writeChar(int data) throws IOException;
      public void writeInt(int data) throws IOException;
      public void writeLong(long data) throws IOException;
      public void writeFloat(float data) throws IOException;
      public void writeDouble(double data) throws IOException;
      public void writeBytes(String data) throws IOException;
      public void writeChars(String data) throws IOException;
      public void writeUTF(String data) throws IOException;

      // Inner class to provide access to serializable fields.
      abstract static public class PutField {
         public void put(String name, boolean value) throws IOException, IllegalArgumentException;
         public void put(String name, char data) throws IOException, IllegalArgumentException;
         public void put(String name, byte data) throws IOException, IllegalArgumentException;
         public void put(String name, short data) throws IOException, IllegalArgumentException;
         public void put(String name, int data) throws IOException, IllegalArgumentException;
         public void put(String name, long data) throws IOException, IllegalArgumentException;
         public void put(String name, float data) throws IOException, IllegalArgumentException;
         public void put(String name, double data) throws IOException, IllegalArgumentException;
         public void put(String name, Object data) throws IOException, IllegalArgumentException;
      }

      public void useProtocolVersion(int version) thows IOException;
      protected ObjectOutputStream()  throws IOException;
      protected writeObjectOverride() throws NotActiveException, IOException;
  }

 

A TERMINER

21.1.4 Implanter l'interface Serializable

Un objet est dit Serializable que si elle implante l'interface Serializable. L'interface Serializable définie par Java est une interface vide.

 
package java.io;
public interface Serializable 

Autrement dit, pour qu'un objet puisse être écrit ou lu, il n'est pas nécessaire de définir quoique ce soit. Il suffit juste de signaler, lors de la classe, que celle-ci implante l'interface Serializable. Il existe une implantation par défaut de la méthode readObject et writeObject.

 

   import java.io.*;
   import java.util.*;

   class UneDate implements Serializable {
      static int ii = 2;
      int jour, mois, année;
      public UneDate(int j, int m, int a) {
         jour = j; mois = m; année = a;
      }
   }

   public class Serial {
      public static void main(String args[]) throws Exception {
         FileOutputStream f = new FileOutputStream("Resultat");
         ObjectOutput s = new ObjectOutputStream(f);
         s.writeObject("Des dates");
         UneDate [] dd = {new UneDate(25, 12, 98), new UneDate(15, 9, 57)};
         s.writeObject(dd);
         s.flush();
      
         FileInputStream ff = new FileInputStream("tmp");
         ObjectInput t = new ObjectInputStream(ff);
         String str = (String) t.readObject();
         UneDate date[] = (UneDate[])t.readObject();
      
         System.out.println(str +"\n");
	 for (int i=0; i<date.length ; i++)
            System.out.println(date[i].jour + " " + date[i].mois + " " + date[i].année);
      }
   }

Dans certains cas, l'implantation par défaut ne convient pas et il faut alors redéfinir les méthodes readObject et writeObject. Voici un squelette de ces deux méthodes:

 
   private void writeObject(ObjectOutputStream s) throws IOException {
      s.defaultWriteObject();
      // code particularisé
   }

private void readObject(ObjectInputStream s) throws IOException { s.defaultReadObject(); // code particularisé conforme à l'écriture ... // suivi d'éventuelles mises à jour de l'objet }

Supposons que, de notre classe Date ci-dessus, nous ne voulions sauvegarder que le jour et le mois et non pas l'année. Il faut alors redéfinir les méthodes writeObject et readObject.

 class UneDate98 implements Serializable 
      static int ii = 2;
      int jour, mois, année;
      public UneDate98(int j, int m, int a) 
         jour = j; mois = m; année = a;
      
      private void writeObject(ObjectOutputStream s) throws IOException 
         s.defaultWriteObject();
         s.writeInt(jour);
         s.writeInt(mois);
      
      private void readObject(ObjectInputStream s)
                    throws OptionalDataException, ClassNotFoundException, IOException 
         s.defaultReadObject();
         jour = s.readInt();
         mois = s.readInt();
         année = 1998;
      
   
 

21.1.5 Implanter l'interface Externalizable

 

public interface Externalizable extends Serializable {
      public void writeExternal(ObjectOutput out) throws IOException;
      public void readExternal(ObjectInput in) throws IOException, java.lang.ClassNotFoundException;
   }

21.1.6 Protéger des données (transient)


next up previous contents index
Next: 22 Compression des données Up: Java: Le langage Previous: 20 Threads
Touraivane
6/12/1998