:: Enseignements :: IMAC :: IMAC2 :: IMAC2 2011-2012 :: Programmation Java ::
[LOGO]

Entrées/sorties et sérialisation


Ce TD aborde les entrées/sorties de la bibliothèque java.io ainsi que les capacités de sérialisation de Java (permettant de sauvegarder des objets dans des fichiers).

Exercice 1 - Écriture/lecture de bibliothèque

Nous aimerions que notre bibliothèque puisse survivre à l'exécution de la JVM. Pour cela nous choisissons de l'enregistrer dans un fichier. Ce fichier pourra ensuite être lu pour que les livres qui y figurent puissent être rajoutés dans une nouvelle bibliothèque.

À cet effet, on écrit deux méthodes de rôle symétrique :
  • void writeMedias(OutputStream out) qui écrit les médias de la bibliothéque dans le flux sortant;
  • void readMedias(InputStream in) lisant les médias provenant d'un flux entrant pour les ajouter dans la bibliothèque courante.

On écrira les médias les uns à la suite des autres sous forme de lignes de texte respectant le format suivant :
  • Type de média (Book, Comic, VideoDVD...)
  • Premier attribut du média
  • Deuxième attribut du média
  • ...
  • Ligne vide de séparation

Exercice 2 - Sérialisation

Nous venons (sans vraiment le savoir) d'écrire des méthodes permettant la sérialisation d'une bibliothèque. Le code produit est cependant peu évolutif : une disjonction de cas est réalisée dans les méthodes d'écriture et de lecture afin de gérer les différents types de médias ; le support d'un nouveau média ou la modification d'une classe de média existante nécessiterait de modifier ces deux méthodes. Il serait plus raisonnable de séparer les méthodes de sérialisation de chacune des classes manipulées dans des méthodes distinctes.

Java offre des capacités de sérialisation automatique : les classes susceptibles d'être sérialisées doivent implanter l'interface Serializable. Il est inutile d'implanter soi-même les méthodes de sérialisation : Java analyse les classes par introspection et écrit les champs non-marqués comme transient. La gestion de la sérialisation peut cependant s'avérer délicate si la classe a évolué entre la sérialisation d'un objet et sa désérialisation (renommage de champs, changement de type de champs...). On peut associer à chaque classe un champ static final long serialVersionUID = x; pour spécifier son numéro de version : si la version de la classe stockée et la classe courante divergent, un exception sera levée lors de la lecture de l'objet.

La sérialisation standard est facile à mettre en oeuvre mais s'avère lente à l'exécution et peu flexible. L'interface Externalizable propose deux méthodes à implanter afin d'expliciter manuellement la procédure de sérialisation/désérialization d'un objet.

  • Dans un premier temps, on testera la sérialisation standard avec l'interface Serializable. Examiner le fichier de sérialisation créé. Essayer de marquer certains champs comme transient : que peut-on remarquer ?
  • Dans un second temps, on implantera intelligemment l'interface Externalizable pour Library et les différents médias afin de sauvegarder soi-même les champs intéressants.