
FAQ Fichiers, flux et r�seauxConsultez toutes les FAQ
Nombre d'auteurs : 15, nombre de questions : 95, derni�re mise � jour : 21 mars 2016 Ajouter une question
Cette FAQ a �t� r�alis�e � partir des questions fr�quemment pos�es sur le forum Java de http://java.developpez.com ainsi que l'exp�rience personnelle des auteurs.
Nous tenons � souligner que cette FAQ ne garantit en aucun cas que les informations qu'elle propose sont correctes. Les auteurs font leur maximum, mais l'erreur est humaine. Cette FAQ ne pr�tend pas non plus �tre compl�te. Si vous trouvez une erreur, ou que vous souhaitez nous aider en devenant r�dacteur, lisez ceci.
Sur ce, nous vous souhaitons une bonne lecture.
- Comment s�rialiser un objet ?
- Comment r�cup�rer un objet s�rialis� ?
- Si je fais �voluer ma classe, pourrai-je relire les objets d�j� s�rialis�s ?
- Que faire si je n'avais pas mis de serialVersionUID et que ma classe a chang� ?
- Comment emp�cher la s�rialisation d'un membre de ma classe ?
- Comment g�rer sa propre s�rialisation ?
- Comment g�rer les super-classes non s�rialisables ?
- Comment v�rifier l'�tat de l'objet apr�s la d�s�rialisation ?
- Comment s�rialiser un Bean en XML ?
- Comment s�rialiser un objet en XML ?
- Comment s�rialiser un objet en JSON ?
Le but est de la s�rialisation est de sauvegarder une instance d'un objet particulier.
Attention�: l'objet � s�rialiser, de m�me que ses sous-membres, doit impl�menter l'interface java.io.Serializable�!
Dans cet exemple, nous allons sauvegarder des options param�trables par l'utilisateur�:
Code Java : | S�lectionner tout |
1 2 3 4 | Options options = new Options(); // Notre classe impl�mente Serializable. try (ObjectOutputStream output = new ObjectOutputStream(new FileOutputStream("options.tmp"))) { output.writeObject(options); } |
Si votre objet � ou un de ses sous-membres � n�impl�mente pas l'interface java.io.Serializable, cette m�thode g�n�rera une exception de type java.io.NotSerializableException.
Note�: il est possible de sauvegarder plusieurs objets dans le m�me flux.
L'instance d'un objet s�rialis� (c'est-�-dire, sauvegard� � l'aide de l'interface java.io.Serializable) se r�cup�re comme suit�:
Code Java : | S�lectionner tout |
1 2 3 | try (ObjectInputStream input = new ObjectInputStream(new FileInputStream("options.tmp"))) { Options options = (Options) input.readObject(); } |
Si la classe que vous tentez de d�s�rialiser n'est pas disponible sur le CLASSPATH, cette m�thode g�n�rera une exception de type java.lang.ClassNotFoundException.
Note�: il est possible de lire plusieurs objets depuis le m�me flux.
Oui, si vous prenez la pr�caution d'indiquer la valeur du membre statique serialVersionUID dans votre classe, et que cette valeur reste constante. D�finir cette valeur prot�ge des �volutions mineures telles que l'ajout ou le retrait d'attributs ou m�thodes.
Par exemple�:
Code Java : | S�lectionner tout |
1 2 3 4 5 6 7 | package test; public final class MaClasse implements java.io.Serializable { private static final long serialVersionUID = 1515L; [...] } |
L'outil serialver inclus dans le JDK offre le calcul d'un serialVersionUID � partir de l'�tat pr�sent d'une classe�:
Code Console : | S�lectionner tout |
1 2 | $ serialver -classpath build/classes test.MaClasse test.MaClasse: static final long serialVersionUID = -4630845128859230043L; |
Il vous est alors possible de recopier la valeur obtenue dans la d�finition de la classe.
Si vous avez modifi� la d�finition de votre classe sans y avoir inclus de serialVersionUID, lisez bien le message d'erreur de l'exception qui est g�n�r�e lorsque vous tentez de d�s�rialiser la classe. Ce message mentionne une valeur de serialVersionUID�; il vous suffit alors d'affecter cette valeur � la nouvelle version de la classe.
Par exemple, si la d�s�rialisation renvoie ce message d'erreur�:
Code Console : | S�lectionner tout |
Exception in thread "main" java.io.InvalidClassException: test.MaClasse; local class incompatible: stream classdesc serialVersionUID = -2335767472728093557, local class serialVersionUID = -4630845128859230043
Il vous suffit alors de d�clarer dans votre classe�:
Code Java : | S�lectionner tout |
private static final long serialVersionUID = -2335767472728093557L;
Vous devriez d�sormais �tre en mesure de la d�s�rialiser.
Vous pouvez emp�cher la s�rialisation d'un membre de votre classe en utilisant le mot-cl� transient.
Code Java : | S�lectionner tout |
1 2 3 4 5 6 7 8 9 | public class MaClasse implements java.io.Serializable { private static final long serialVersionUID = 1515L; // Entier transient. public transient int var1 = 4; // Entier normal. public int var2 = 19; } |
Ici, le membre var1 ne sera pas s�rialis� et, lors de la d�s�rialisation, elle prendra la valeur 0, malgr� la pr�sence de la valeur par d�faut�4. L'attribution d'une valeur par d�faut se fait lors de l'instanciation de l'objet�! Or, la m�thode consistant � lire un objet depuis un fichier ne cr�e pas cette instance explicitement. Donc var1 n'est jamais initialis� avec sa valeur par d�faut. De plus, comme cet attribut est transient, il n'est pas �crit dans le fichier. Cela implique que var1 ne re�oit aucune valeur et contient donc 0.
Ce mot-cl� trouve des applications d�s lors qu'une donn�e sensible ne doit en aucun cas appara�tre dans un fichier. Un mot de passe par exemple. Mais ce mot-cl� peut �galement permettre de ��remettre � z�ro�� certaines valeurs. Dans le cas d'un jeu, on pourra ainsi ne pas sauvegarder le temps de jeu depuis le d�but de la partie.
M�thodes customisables
Il est possible de d�finir quatre m�thodes distinctes dans notre classe de mani�re � customiser la s�rialisation et la d�s�rialisation d'une classe �:
- private void writeObject(ObjectOutputStream) - si elle est pr�sente, cette m�thode est utilis�e pour s�rialiser l'objet dans le flux�;
- private void readObject(ObjectInputStream) - si elle est pr�sente, cette m�thode est utilis�e pour d�s�rialiser l'objet depuis le flux�;
- private Object writeReplace() - si elle est pr�sente, cette m�thode sera invoqu�e apr�s la s�rialisation et l'objet produit sera �crit sur le flux�;
- private Object readReplace() - si elle est pr�sente, cette m�thode sera invoqu�e apr�s la d�s�rialisation et l'objet produit sera retourn� � la m�thode appelante. Cette m�thode permet d�impl�menter la d�s�rialisation du
patron de conception
singleton.
Code Java : | S�lectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | public class MaClass implements Serializable { private static final long serialVersionUID = 1515L; private int value = 25; private void writeObject(ObjectOutputStream out) throws IOException { // S�rialisation de l'objet. out.writeInt(value); [...] } private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { // D�s�rialisation de l'objet. // Lecture des membres dans le m�me ordre que celui dans lequel ils ont �t� �crits dans le flux. value = in.readInt(); [...] } } |
Attention�: les m�thodes writeObject() et readObject() ne sont pas invoqu�es si leur niveau d�acc�s n'est pas private. Ici, les impl�mentations de la s�rialisation et de la d�s�rialisation restent cach�es aux autres classes et aux classes filles.
java.io.Externalizable
Il est �galement possible de customiser la s�rialisation et la d�s�rialisation d'une classe en impl�mentant l'interface java.io.Externalizable et en impl�mentant les m�thodes writeExternal() et readExternal() d�finies dans cette interface, ce qui permet plus de contr�les sur les valeurs enregistr�es et lues dans le flux.
Code Java : | S�lectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | public class MaClass implements Externalizable { private static final long serialVersionUID = 1515L; private int value = 25; @Override public void writeExternal(ObjectOutput out) throws IOException { // S�rialisation de l'objet. out.writeInt(value); [...] } @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { // D�s�rialisation de l'objet. // Lecture des membres dans le m�me ordre que celui dans lequel ils ont �t� �crits dans le flux. value = in.readInt(); [...] } } |
Ces m�thodes seront invoqu�es par les flux d'objets lors de la s�rialisation et de la d�s�rialisation. Cette mani�re de faire a le d�savantage de rendre visible le processus de s�rialisation/d�s�rialisation aux autres classes et aux classes filles.
Un probl�me risque de se pr�senter � vous lorsque votre classe s�rialisable h�rite d'une classe qui ne l'est pas. Par exemple�:
Code Java : | S�lectionner tout |
1 2 3 4 5 6 7 8 9 10 | public class MaSuperClasse { protected int val1 = 10; protected int val2 = 55; } public class MaClasse extends MaSuperClasse implements Serializable { private static final long serialVersionUID = 1515L; private int val3 = -15; } |
En effet, lors de la d�serialisation, seul val3 contiendra une valeur correcte. Cela est d� au fait que la classe m�re n'est pas s�rialisable et donc le contexte de val1 et val2 n'est pas sauvegard� ou restaur�. Il est possible de corriger ce souci en s�rialisant/d�s�rialisant manuellement l��tat de la super-classe en d�finissant les m�thodes writeObject() et readObject() dans notre classe s�rialisable�:
Code Java : | S�lectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | public class MaClasse extends MaSuperClasse implements Serializable { private static final long serialVersionUID = 1515L; private int val3 = -15; private void writeObject(ObjectOutputStream out) throws IOException { // Sauvegarde du contexte de la classe s�rialisable. out.defaultWriteObject(); // Sauvegarde manuelle des �l�ments de la classe m�re. out.writeInt(val1); out.writeInt(val2); } private void readObject(ObjectInputStream in) throws ClassNotFoundException, IOException { // Restauration du contexte de la classe s�rialisable. in.defaultReadObject(); // Restauration manuelle des �l�ments de la classe m�re. // Lecture des membres dans le m�me ordre que celui dans lequel ils ont �t� �crits dans le flux. val1 = in.readInt(); val2 = in.readInt(); } } |
Nous pouvons invoquer les m�thodes defaulWriteObject() sur l'instance d'ObjectOutputStream et defaultReadObject() sur l'instance d'ObjectInputStream pour g�rer automatiquement l��tat des variables de MaClasse, ce qui �vite de devoir manuellement sauvegarder et restaurer val3. Il ne nous reste plus alors qu'� �crire la s�rialisation et la d�s�rialisation manuelle de val1 et val2 qui appartiennent � la classe m�re.
Pour v�rifier l��tat de l'objet apr�s la d�s�rialisation, vous pouvez impl�menter l'interface java.io.ObjectInputValidation et d�finir la m�thode validateObject() qui permet de tester l��tat de l'objet venant d��tre restaur�. Il vous faut ensuite enregistrer votre valideur sur l'instance d'ObjectInputStream au moment de la lecture dans la m�thode readObject().
Code Java : | S�lectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | public class MaClasse implements Serializable, ObjectInputValidation { private static final long serialVersionUID = 1515L; public int value = 8; private void readObject(ObjectInputStream in) throws ClassNotFoundException, IOException { // Enregistrement du valideur avec la priorit� 0. in.registerValidation(this, 0); // Lecture. in.defaultReadObject(); // La validation sera effectu�e lorsque nous quittons cette m�thode. } @Override public void validateObject() throws InvalidObjectException { // Effectue des tests de validation. if (value == 0) { throw new InvalidObjectException("Value invalide�!"); } } } |
Ici, la m�thode validateObject() qui sert � tester la validation sera invoqu�e apr�s que le processus de d�s�rialisation a quitt� la m�thode readObject(). Le niveau de priorit� sp�cifi� influence l'ordre d'invocation des valideurs lorsqu'il y en a plusieurs qui sont enregistr�s sur le flux.
Il est possible de sauvegarder et de restaurer l��tat d'objets conformes � la norme Java Beans de plusieurs mani�res. La classe � sauvegarder ne doit pas n�cessairement impl�menter l'interface java.io.Serializable et toutes les m�thodes utilisables dans le m�canisme de s�rialisation classique sont compl�tement ignor�es.
Attention�: contrairement � une s�rialisation classique qui sauvegarde tous les membres de l'objet, ici, seuls les membres qui r�pondent � au moins un des crit�res suivants seront sauvegard�s dans le fichier XML�:
- membres en acc�s public�;
- membres disposant � la fois d'un getter et d'un setter.
Ainsi, un membre private ne disposant pas de getter ou de setter sera totalement ignor�, de m�me qu'un membre protected qui ne dispose que d'un getter ou que d'un setter. Ces m�thodes de sauvegarde de l'objet ne sauvegardent pas non plus les �couteurs qui �taient enregistr�s sur les diverses propri�t�s du bean.
Par exemple�:
Code Java : | S�lectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | package test; public class MaClasse { public int val0; private int val1; private int val2; private int val3; public int getVal1() { return val1; } public void setVal1(int value) { this.val1 = value; } public int getVal2() { return val2; } public void setVal3(int val3) { this.val3 = val3; } } |
Nous avons�:
- val0 est en acc�s public�;
- val1 est en acc�s private avec un getter et un setter�;
- val2 est en acc�s private avec un getter�;
- val3 est en acc�s private avec un setter.
XMLEncoder & XMLDecoder
� partir du JDK�1.4, il est possible de sauvegarder et de restaurer l��tat d'un bean en utilisant respectivement les classes java.bean.XMLEncoder et java.bean.XMLDecoder. La mani�re de proc�der est similaire � celle de la s�rialisation et de d�s�rialisation classique.
La classe java.bean.XMLEncoder permet d��crire du XML � partir de notre objet�:
Code Java : | S�lectionner tout |
1 2 3 | try (XMLEncoder output = new XMLEncoder(new FileOutputStream("fichier.xml"))) { output.writeObject(monObjet); } |
La classe java.bean.XMLDecoder permet de cr�er un nouvel objet � partir du contenu du XML�:
Code Java : | S�lectionner tout |
1 2 3 | try (XMLDecoder input = new XMLDecoder(new FileInputStream("fichier.xml"))) { final MaClasse monObject = (MaClasse) input.readObject(); } |
Si nous faisons�:
Code Java : | S�lectionner tout |
1 2 3 4 5 6 7 | MaClasse monObjet = new MaClasse(); monObjet.val0 = 98; monObjet.setVal1(105); monObjet.setVal3(481); try (XMLEncoder output = new XMLEncoder(new FileOutputStream("fichier.xml"))) { output.writeObject(monObjet); } |
Ceci nous donnera un fichier XML similaire �:
Code XML : | S�lectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <?xml version="1.0" encoding="UTF-8"?> <java version="1.8.0_51" class="java.beans.XMLDecoder"> <object class="testfor.MaClasse" id="MaClasse0"> <void class="testfor.MaClasse" method="getField"> <string>val0</string> <void method="set"> <object idref="MaClasse0"/> <int>98</int> </void> </void> <void property="val1"> <int>105</int> </void> </object> </java> |
Ici, seuls les membres val0 (qui est en acc�s public) et val1 (qui a un getter et un setter) sont sauvegard�s dans le fichier XML.
API JAXB
� partir du JDK�6, il est possible de sauvegarder et de restaurer l��tat d'un bean en utilisant l'API JAXB (Java Architecture for XML Binding ou Architecture Java pour les liaisons XML).
Tout d'abord nous devons modifier l�g�rement la d�finition de notre classe pour la marquer avec l'annotation javax.xml.bind.annotation.XmlRootElement�:
Code Java : | S�lectionner tout |
1 2 3 4 5 6 7 | package test; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement public class MaClasse { [...] |
Il nous faudra ensuite cr�er un contexte de type javax.xml.bind.JAXBContext en faisant�:
Code Java : | S�lectionner tout |
JAXBContext context = JAXBContext.newInstance(MaClasse.class);
Nous pouvons invoquer la m�thode createMarshaller() du contexte pour obtenir un objet de type javax.xml.bind.Marshaller qui se chargera de faire la transformation en XML en invoquant sa m�thode marshal()�:
Code Java : | S�lectionner tout |
1 2 3 4 5 | Marshaller marshaller = context.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); try (OutputStream output = new FileOutputStream("fichier.xml")) { marshaller.marshal(monObjet, output); } |
Nous pouvons invoquer la m�thode createUnmarshaller() du contexte pour obtenir un objet de type javax.xml.bind.Unmarshaller qui se chargera de cr�er notre objet � partir du contenu du XML en invoquant sa m�thode unmarshal()�:
Code Java : | S�lectionner tout |
1 2 3 4 | Unmarshaller unmarshaller = context.createUnmarshaller(); try (InputStream input = new FileInputStream("fichier.xml")) { final MaClasse monObjet = (MaClasse) unmarshaller.unmarshal(input); } |
Par exemple, si nous faisons�:
Code Java : | S�lectionner tout |
1 2 3 4 5 6 7 | MaClasse monObjet = new MaClasse(); monObjet.val0 = 98; monObjet.setVal1(105); monObjet.setVal3(481); try (OutputStream output = new FileOutputStream("fichier.xml")) { marshaller.marshal(monObjet, output); } |
Ceci nous donnera un fichier XML similaire �:
Code XML : | S�lectionner tout |
1 2 3 4 5 | <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <maClasse> <val0>98</val0> <val1>105</val1> </maClasse> |
Ici, aussi seuls les membres val0 et val1 sont sauvegard�s dans le fichier XML.
Il est possible de s�rialiser/d�s�rialiser enti�rement un objet quelconque en XML en utilisant la biblioth�que tierce XStream. La classe � sauvegarder ne doit pas n�cessairement impl�menter l'interface java.io.Serializable et toutes les m�thodes utilisables dans le m�canisme de s�rialisation classique sont compl�tement ignor�es. Cependant, ici, tous les membres de la classe, m�me ceux en acc�s private ou sans getter ou sans setter seront sauvegard�s et restaur�s.
Tout d'abord, il nous faut obtenir un contexte XStream�:
Code Java : | S�lectionner tout |
XStream xstream = new XStream();
Pour l��criture, il suffit d'invoquer l'une des variantes de la m�thode toXML() du contexte�:
Code Java : | S�lectionner tout |
1 2 3 | try (FileOutputStream output = new FileOutputStream("fichier.xml")) { xstream.toXML(monObjet, output); } |
Pour la lecture, il suffit d'invoquer l'une des variantes de la m�thode fromXML() du contexte�:
Code Java : | S�lectionner tout |
1 2 3 | try (FileInputStream output = new FileInputStream("fichier.xml")) { MaClasse monObjet = (MaClasse) xstream.fromXML(output); } |
Par exemple, reprenons notre classe toute simple�:
Code Java : | S�lectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | package test; public class MaClasse { public int val0; private int val1; private int val2; private int val3; public int getVal1() { return val1; } public void setVal1(int value) { this.val1 = value; } public int getVal2() { return val2; } public void setVal3(int val3) { this.val3 = val3; } } |
Si nous faisons�:
Code Java : | S�lectionner tout |
1 2 3 4 5 6 7 | MaClasse monObjet = new MaClasse(); monObjet.val0 = 98; monObjet.setVal1(105); monObjet.setVal3(481); try (FileOutputStream output = new FileOutputStream("fichier.xml")) { xstream.toXML(monObjet, output); } |
Nous obtenons un fichier XML similaire �:
Code XML : | S�lectionner tout |
1 2 3 4 5 6 | <test.MaClasse> <val0>98</val0> <val1>105</val1> <val2>0</val2> <val3>481</val3> </test.MaClasse> |
Ici, tous les membres de notre classe ont �t� export�s vers le fichier XML et restaur�s lors de la d�s�rialisation.
Note�: XStream supporte beaucoup de param�tres optionnels�; ainsi, il est possible de configurer le contexte � sa cr�ation pour qu'il utilise des pilotes particuliers. Il est �galement possible de mapper des noms de classes sur des �l�ments sp�cifiques du DOM�:
Code Java : | S�lectionner tout |
1 2 | xstream.alias("person", Person.class); xstream.alias("phonenumber", PhoneNumber.class); |
Il est possible de s�rialiser/d�s�rialiser enti�rement un objet quelconque en JSON en utilisant la biblioth�que tierce XStream. La classe � sauvegarder ne doit pas n�cessairement impl�menter l'interface java.io.Serializable et toutes les m�thodes utilisables dans le m�canisme de s�rialisation classique sont compl�tement ignor�es. Cependant, ici, tous les membres de la classe, m�me ceux en acc�s private ou sans getter ou sans setter seront sauvegard�s et restaur�s.
XStream dispose de deux pilotes permettant de manipuler du JSON�:
- com.thoughtworks.xstream.io.json.JsonHierarchicalStreamDriver - permet de s�rialiser un objet au format JSON.
- com.thoughtworks.xstream.io.json.JettisonMappedXmlDriver - permet de s�rialiser et d�s�rialiser un objet au format JSON.
Tout d'abord, il nous faut obtenir un contexte XStream utilisant le pilote choisi�:
Code Java : | S�lectionner tout |
XStream xstream = new XStream(new JettisonMappedXmlDriver());
Pour l��criture, il suffit d'invoquer l'une des variantes de la m�thode toXML() du contexte�:
Code Java : | S�lectionner tout |
1 2 3 | try (FileOutputStream output = new FileOutputStream("fichier.json")) { xstream.toXML(monObjet, output); } |
Pour la lecture, il suffit d'invoquer l'une des variantes de la m�thode fromXML() du contexte�:
Code Java : | S�lectionner tout |
1 2 3 | try (FileInputStream output = new FileInputStream("fichier.json")) { MaClasse monObjet = (MaClasse) xstream.fromXML(output); } |
Par exemple, reprenons notre classe toute simple�:
Code Java : | S�lectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | package test; public class MaClasse { public int val0; private int val1; private int val2; private int val3; public int getVal1() { return val1; } public void setVal1(int value) { this.val1 = value; } public int getVal2() { return val2; } public void setVal3(int val3) { this.val3 = val3; } } |
Si nous faisons�:
Code Java : | S�lectionner tout |
1 2 3 4 5 6 7 | MaClasse monObjet = new MaClasse(); monObjet.val0 = 98; monObjet.setVal1(105); monObjet.setVal3(481); try (FileOutputStream output = new FileOutputStream("fichier.json")) { xstream.toXML(monObjet, output); } |
Nous obtenons un fichier JSON similaire �:
Code JSON : | S�lectionner tout |
1 2 3 4 5 6 7 8 | { "test.MaClasse": { "val0": 98, "val1": 105, "val2": 0, "val3": 481 } } |
Ici, tous les membres de notre classe ont �t� export�s vers le fichier JSON et restaur�s lors de la d�s�rialisation.
Proposer une nouvelle r�ponse sur la FAQ
Ce n'est pas l'endroit pour poser des questions, allez plut�t sur le forum de la rubrique pour �aLes sources pr�sent�es sur cette page sont libres de droits et vous pouvez les utiliser � votre convenance. Par contre, la page de pr�sentation constitue une �uvre intellectuelle prot�g�e par les droits d'auteur. Copyright � 2025 Developpez Developpez LLC. Tous droits r�serv�s Developpez LLC. Aucune reproduction, m�me partielle, ne peut �tre faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'� trois ans de prison et jusqu'� 300 000 � de dommages et int�r�ts.