Partage
  • Partager sur Facebook
  • Partager sur Twitter

Serialisation / Deserialisation

Serialisation / Deserialisation d'un ArrayList

Anonyme
    4 août 2017 à 1:41:47

    Bonjour,

    Je suis en train d'essayer de faire le TP 2 du cours Java.

    J'ai creer une classe main que voici :

    package tp2;
    
    public class main 
    {
    	public static void main(String[] args) 
    	{
    		Garage garage = new Garage();
    		
    		Vehicule v1 = new Lagouna();
    		garage.addVoiture(v1);
    		
    		Vehicule v2 = new D4();
    		garage.addVoiture(v2);
    		
    		Vehicule v3 = new A330B();
    		garage.addVoiture(v3);
    		
    		
    		System.out.println(garage);
    	}
    }

    Une classe Vehicule que voici :

    package tp2;
    
    import java.io.Serializable;
    import java.util.List;
    
    public class Vehicule implements Option, Serializable
    {
    	public enum marque
    	{
    		RENO, PIGEOT, TROEN;
    	}
    	
    	protected double prix;
    	protected String nom;
    	protected List<Option> option;
    	protected marque nomMarque;
    	
    	@Override
    	public double getPrix() 
    	{
    		
    		return 0;
    	}
    }

    Une classe Lagouna que voici :

    package tp2;
    
    public class Lagouna extends Vehicule
    {
    	public Lagouna()
    	{
    		this.nom = "Lagouna";
    		this.nomMarque = marque.RENO;
    	}
    	
    	@Override
    	public String toString() 
    	{
    		return "";
    	}
    }

    Une classe D4 et une autre A330B qui sont les memes que Lagouna sauf pour les affectations de variables.


    La plus grosse classe est la classe Garage.

    Elle comprend un tableau List<Vehicule> voituresAvS qui se rempli a chaque appel a la fonction addVoiture.

    A chaque fois qu'un vehicule s'ajoute je serialise ce tableau dans un fichier garage.ser, je fais en sorte que la serialisation se fasse a la fin du fichier sans effacer son contenu a chaque fois qu on relance le programme.

    Tout ca ca fonctionne. Du moins ca a l air ^^

    Le probleme est la deserialisation, je voudrais deserialiser dans un autre tableau qui s appel List<Vehicule> voituresApS, et le probleme c est qu il ne deserialise que pour le premier vehicule et pas pour les autres.

    quand je fais : (avec le tableau qui n a pas encore ete serialisé) ca fonctionne, je vois toutes les voitures ajoutées via le main

    public String toString() 
    	{
    		deSerialize();
    		
    		for (Vehicule vehicule : voituresAvS) 
    		{
    			System.out.printf("+ Voiture %s ", vehicule.nomMarque);
    			System.out.printf(" : %s\n", vehicule.nom);
    		}
    		return "";
    	}

    Quand je fais la meme manip avec le tableau qui a ete déserialisé ca m affiche que le premier vehicule ?? La est mon probleme !!

    public String toString() 
    	{
    		deSerialize();
    		
    		for (Vehicule vehicule : voituresApS) 
    		{
    			System.out.printf("+ Voiture %s ", vehicule.nomMarque);
    			System.out.printf(" : %s\n", vehicule.nom);
    		}
    		return "";
    	}

    La classe Garage :

    package tp2;
    
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    import java.io.Serializable;
    import java.util.ArrayList;
    import java.util.List;
    
    public class Garage implements Serializable
    {
    	private static final long serialVersionUID = 201708031301L;
    	private static int nbDeVoiture = 0;
    	private List<Vehicule> voituresAvS = new ArrayList<>(); //AvS = avant serialisation
    	private List<Vehicule> voituresApS = new ArrayList<>(); //ApS = apres serialisation
    	
    	// Cette methode ajoute un objet Vehicule au tableau voitures
    	public void addVoiture(Vehicule voit)
    	{
    		voituresAvS.add(voit);
    		serialize(voituresAvS);
    		nbDeVoiture++;
    	}
    	
    	// Cette methode serialize l'ArrayList voituresAvS creer avec la methode addVoiture
    	public void serialize(List<Vehicule> voituresAvS)
    	{
    		try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File("./garage.ser"), true)))
    		{
    			oos.writeObject(voituresAvS);
    		}
    		catch (IOException e)
    		{
    			e.printStackTrace();
    		}
    	}
    	
    	// Cette methode deserialize le fichier garage.ser généré par la methode serialize
    		public void deSerialize()
    		{
    			try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("./garage.ser"))))
    			{
    				voituresApS = ((List<Vehicule>)ois.readObject());
    			}
    			catch (IOException e)
    			{
    				e.printStackTrace();
    			} 
    			catch (ClassNotFoundException e) 
    			{
    				e.printStackTrace();
    			}
    		}
    	
    	@Override
    	public String toString() 
    	{
    		deSerialize();
    		
    		for (Vehicule vehicule : voituresAvS) 
    		{
    			System.out.printf("+ Voiture %s ", vehicule.nomMarque);
    			System.out.printf(" : %s\n", vehicule.nom);
    		}
    		return "";
    	}
    }

    Merci de votre aide.



    -
    Edité par Anonyme 4 août 2017 à 1:43:25

    • Partager sur Facebook
    • Partager sur Twitter
      9 août 2017 à 19:03:25

      tu peux toi meme faire une forme de deserialization en créant une fonction toString de ton objet et en toute logique fromString ton objet devras donc prendre un élément propre a lui tel qu'un String (nom) un id (int) enfin quelque chose d'unique genre un UUID ou un trucs du genre apres une hashmap<identifiant, TonObjet> stocks = new HashMap();

      et dans ton constructeur tu rajoute un paramtre du genre

      public monObjet(un_id){

      //i_ci tu initialises tes varibles locales

      stocks.put(un_id, this);

      }

      en espérant t'avoir aidé ^^

      • Partager sur Facebook
      • Partager sur Twitter
      Coding, Study, Repeat;
      Anonyme
        10 août 2017 à 0:33:46

        Salut,

        Depuis j avais abandonné la serialisation/deserialisation et je m etait concentré sur le reste du projet.

        Tout le projet fonctionne correctement, reste plus qu'a me remettre a la serialisation/deserialisation.

        Je pense que je vais changer de methode et serialiser directement le garage une fois rempli de nouveau vehicule.

        Serais ce pas plus simple ?

        Voici le projet en question : ici

        Merci

        • Partager sur Facebook
        • Partager sur Twitter
          10 août 2017 à 21:17:33

          Pas idiot de dezerialiser le garage directe a voir ce que ca donne j'irais voir ca apres ^^
          • Partager sur Facebook
          • Partager sur Twitter
          Coding, Study, Repeat;
            10 août 2017 à 23:02:59

            Bonjour, 

            J'étais en train de me dire la même chose, il vaut mieux sérialiser et désérialiser tout le garage d'un coup non ? (Enfin, pour la sérialisation, je dirais à chaque fois qu'on ajoute une voiture et qu'il faut en même temps écraser la sauvegarde précédente...)

            Par contre je me demande comment désérialiser... Je pensais à quelque chose de ce genre, mais ça ne fonctionne pas (je n'ai pas mis les try catch pour l'instant)

            public Garage()
            {
               File garageFile = new File("garage.txt");
               if(!garageFile.exists() || garageFile.length()==0)
               System.out.println("Aucune voiture sauvegardée");
               else
               {
                  ObjectInputStream ois = new ObjectInputStream(new BufferedInputStream(new FileInputStream(garageFile)));
                  this = (Garage)ois.readObject();
               }
            }

            On peut très bien ajouter un getList au garage et ça pourrait régler le problème, mais je ne suis pas trop fan, donc s'il y a une autre solution...

            Je sais, je m'incruste mais comme je pense qu'on a la même question, on peut peut-être réfléchir ensemble ?

            Merci

            Ccile

            -
            Edité par Ccile 10 août 2017 à 23:05:16

            • Partager sur Facebook
            • Partager sur Twitter
              10 août 2017 à 23:38:49

              Ton garage contient une voiture ou plusieurs donc il faut que tu deserialize ta liste de voiture genre une boucle for et une methode toString dans ta class voiture et logiquement une methode fromString pour récupérer une voiture depuis un chaine de caractere genre si ta 3 voiture

              Une lagouna

              Une mercedes

              et une ferrarie

              (De simples exemples)

              et bah ta chaine de caractere devrait faire un trucs du style

              lagouna.mercedes.ferrari

              et au fromString du split a chaque . enfin j'aurais procèder ainsi

              • Partager sur Facebook
              • Partager sur Twitter
              Coding, Study, Repeat;
                11 août 2017 à 9:46:26

                Pourquoi s'embêter à sérialiser/désérialiser au coup par coup alors qu'on peut sauvegarder un objet complet directement ?

                De plus si t'as des méthodes to et from String la sérialisation n'est pas utile puisque tu peux directement écrire les chaines de caractères dans le fichier...

                Ensuite on pourrait très bien ne sérialiser que la liste de véhicules mais plusieurs points me chagrinent : est-ce que List peut-être sérialiser ? Si on avait beaucoup plus d'attributs, ça ne serait pas exaspérant de devoir faire un à un ? (à condition aussi qu'on puisse sérialiser chacun de ces attributs)

                • Partager sur Facebook
                • Partager sur Twitter
                Anonyme
                  11 août 2017 à 13:29:35

                  salut,

                  Apres reflexion cela me semble pas possible de serializer tout le garage d'un seul coup.

                  Donc comme a ma premiere idée je pense qu il faut serialiser le tableau listVoitures des qu on lui ajoute 1 vehicule a l'interieur.

                  La serialization devrait donc se faire dans la methode addVoitures.

                  Donc la methode addVoiture ressemblerait a ca :

                  public void addVoiture(Vehicule voit)
                  	{
                  		listVoitures.add(voit);
                  		
                  		try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File("./garage.ser"), true)))
                  		{
                  			oos.writeObject(voit);
                  			oos.flush();
                  		} 
                  		catch (IOException e) 
                  		{
                  			e.printStackTrace();
                  		}
                  	}

                  De cette façon je pense que la serialization fonctionne et les véhicules s ajoute a la fin du fichier garage.ser car quand j exécute le programme 1 fois il fait 4ko, je reexecute il fait maintenant 8ko, ensuite 12ko, 16ko etc...

                  Donc je pense que la serialisation c est OK.

                  Reste a le deserialisation...

                  -
                  Edité par Anonyme 11 août 2017 à 13:33:36

                  • Partager sur Facebook
                  • Partager sur Twitter
                    11 août 2017 à 14:41:06

                    Salut,

                    Pourquoi on ne pourrait pas serialiser le garage ? Un peu comme tu le fais pour voitures mais avec tout le garage directement...

                    A moins que ça ne soit un problème de désérialisation après coup. Et en effet, pour régler les problèmes de désérialisation, sérialiser la liste des voitures était une de mes options mais je ne l'aime pas trop :/ Et s'il y avait eut plusieurs listes ? On devrait tout sérialiser/désérialiser ? Un peu casse pied non ?

                    • Partager sur Facebook
                    • Partager sur Twitter
                    Anonyme
                      11 août 2017 à 17:59:40

                      Serialiser le garage reviens a serialiser la List<Vehicule> listVoitures.

                      Donc il faudrait je pense serialiser une fois toutes les voitures creer et ajouter a la List. Donc creer une methode serialiser dans la classe Garage et l appeler au tout debut de la methode toString pour etre sur que la List est bien remplie et ne bougera plus.

                      Tu penses que c est ok ?

                      Ca donnerai 1 truc du genre :

                      package tp2;
                      
                      import java.io.File;
                      import java.io.FileOutputStream;
                      import java.io.IOException;
                      import java.io.ObjectOutputStream;
                      import java.io.Serializable;
                      import java.util.ArrayList;
                      import java.util.List;
                      
                      public class Garage implements Serializable
                      {
                      	private static int nbDeVoiture = 0;
                      	private List<Vehicule> listVoitures = new ArrayList<>();
                      	
                      	public void addVoiture(Vehicule voit)
                      	{
                      		listVoitures.add(voit);
                      		nbDeVoiture++;
                      	}
                      	
                      	public void serialiser()
                      	{
                      		System.err.println("*****  Serialisation  *****");
                      		
                      		try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File("./garage.ser"), true)))
                      		{
                      			oos.writeObject(listVoitures);
                      			oos.flush();
                      		} 
                      		catch (IOException e) 
                      		{
                      			e.printStackTrace();
                      		}
                      	}
                      	
                      	@Override
                      	public String toString() 
                      	{
                      		double total = 0.0;
                      		
                      		if (nbDeVoiture == 0)
                      			System.err.println("Aucune voiture sauvegardée !");
                      		
                      		if (nbDeVoiture > 0)
                      			serialiser();
                      		
                      		System.out.println("****************************");
                      		System.out.println("*  Garage Openclassromms   *");
                      		System.out.print("****************************\n");
                      		for (Vehicule voiture : listVoitures) 
                      		{
                      			System.out.printf("+ Voiture %s ", voiture.getMarque());
                      			System.out.printf(" : %s", voiture.getModele());
                      			voiture.printMoteur();
                      			System.out.printf(" (%.2f€)  ", voiture.getPrix());
                      			System.out.print("[");
                      			voiture.toString();
                      		}
                      		return "";
                      	}
                      }

                      -
                      Edité par Anonyme 11 août 2017 à 18:39:53

                      • Partager sur Facebook
                      • Partager sur Twitter
                        11 août 2017 à 19:35:59

                        Ici en effet, il n'y a qu'un attribut. MAIS je trouve que philosophiquement, ce n'est pas pareil : et s'il y avait plein d'attributs, tu les ferais un à la fois ?

                        Mais bon, une raison pour laquelle je pourrais sérialiser la liste c'est qu'on ne peut pas récupérer le garage dans le constructeur (https://stackoverflow.com/questions/45631084/how-to-save-object-in-java-deserialization-in-constructor?noredirect=1#comment78224529_45631084) et qu'on n'a pas ici de classe gérant le garage.

                        Par contre, là tu sérialises uniquement quand tu fais appelles à toString, c'est normal ? J'aurais sauvegardé à chaque ajout d'une voiture, en effaçant la sauvegarde précédente...

                        • Partager sur Facebook
                        • Partager sur Twitter
                        Anonyme
                          11 août 2017 à 19:45:17

                          Oui je serialise à l appel de toString comme çà je serialise en une seule fois toute la List de véhicules d'un coup et ça l ajoute a la fin du fichier garage.ser

                          Ca a l air de fonctionner la serialisation je pense, il reste a deserialiser...

                          • Partager sur Facebook
                          • Partager sur Twitter
                            11 août 2017 à 23:23:32

                            Oui mais ça sérialise que si tu appelles la méthode toString... Là tu maitrises ton TP de bout en bout donc tu peux le faire, mais imagine que plus tard tu veuilles utiliser tes classes et que t'as oublié qu'il fallait appeler toString ?
                            • Partager sur Facebook
                            • Partager sur Twitter
                            Anonyme
                              12 août 2017 à 2:55:59

                              c est la seule facon que j ai trouvé pour le moment pour serialiser toute la List d un coup...

                              t en est a quel niveau du tp toi ?

                              -
                              Edité par Anonyme 12 août 2017 à 2:57:00

                              • Partager sur Facebook
                              • Partager sur Twitter
                                16 août 2017 à 10:41:36

                                Tu ne peux pas sérialiser à chaque fois que tu ajoutes une voiture ? Il faut faire attention à écraser la sauvegarde à chaque fois, mais ça doit pas être compliqué...

                                Pas très loin, j'ai juste la classe Garage pour l'instant et il faut que je la teste

                                • Partager sur Facebook
                                • Partager sur Twitter
                                Anonyme
                                  16 août 2017 à 20:27:52

                                  J ai enfin terminer complètement ce tp.

                                  Pour ce qui est de la serialisation j appel une fonction serialiser() à chaque fois que j ajoute 1 vehicule dans la List, puis je serialise cette List.

                                  public void addVoiture(Vehicule voit)
                                  	{
                                  		listVoitures.add(voit);
                                  		serialize();
                                  	}



                                  Pour ce qui est de la deserialisation j'effectue cette operation dans le constructeur de Garage.

                                  Voila voila.

                                  • Partager sur Facebook
                                  • Partager sur Twitter

                                  Serialisation / Deserialisation

                                  × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                  × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                                  • Editeur
                                  • Markdown