Ma première sérialisation d'objet

Messages postés
10
Date d'inscription
jeudi 27 septembre 2007
Statut
Membre
Dernière intervention
9 décembre 2008
- - Dernière réponse : Polack77
Messages postés
1100
Date d'inscription
mercredi 22 mars 2006
Statut
Membre
Dernière intervention
15 avril 2018
- 9 déc. 2008 à 12:56
Bonjour à tous,

Je suis débutant en c++, et j'ai un projet ou je dois sauvegarder mes objets afin de pouvoir les recharger après...

Je voulais savoir comment celà ce passe en C++ pour la sérialisation d'objet??

Merci d'avance!

voici un exemple de mes classes:

class Administrateur : public Personne
{
    public:
        // class constructor
        Administrateur(string nom, string prenom, string username, string password);
        virtual void affiche();
        // class destructor
        ~Administrateur();
};
-----------------------
class Equipe
{
     
    private:
   
    string nomequipe;
    int bonusFifa;
    double coefFifa;

    public:
        // class constructor
        Equipe();
        Equipe(string nomequipe, int bonusFifa, double coefFiFA);
        string getNomEquipe(){return nomequipe;}
        int getBonusFifa(){return bonusFifa;}
        double getCoefFifa(){return coefFifa;}
        ~Equipe();
};
-----------------------
class Joueur : public Personne
{
    protected:
        double capital;
        string compte;
    public:
        // class constructor
        Joueur(string nom="", string prenom="", string username="", string password="", double capital=0.0, string compte="");
        virtual void affiche();
        virtual string getNom();
        virtual string getPrenom();
        virtual string getUsername();
        virtual string getPassword();
        virtual double getCapital();
        virtual string getCompte();
       
        // class destructor
        ~Joueur();
};
----------------------
class Match
{
    private:
           
    Equipe *domicile;
    Equipe *exterieure;
    int scoreEquipeA, scoreEquipeB;
   
    public:
        // class constructor
        Match(Equipe *d,Equipe *e, int scoreEquipeA, int scoreEquipeB);
        // class destructor
        Equipe* getDomicile(){return domicile;}
        Equipe* getExterieure(){return exterieure;}
        int getScoreEquipeA(){return scoreEquipeA;}
        int getScoreEquipeB(){return scoreEquipeB;}
        ~Match();
};
--------------------------
class Personne
{
       
        protected:
               string nom,prenom,username,password;
        public:
              
               Personne(string nom, string prenom, string username, string password);
               virtual void affiche();
               virtual string getNom();
               virtual string getPrenom();
               virtual string getUsername();
               virtual string getPassword();
              
               // class destructor
               virtual ~Personne();
};
Afficher la suite 

17 réponses

Messages postés
1100
Date d'inscription
mercredi 22 mars 2006
Statut
Membre
Dernière intervention
15 avril 2018
0
Merci
Salut ,

Alors la serialisation en Dot.Net c'est tout simple (perso du coup je n'es plus le moindre ini dans mes dév. Je sauvegarde mes config/obj/... avec la serialisation )

Petite explication :
Pour faire de la serialisation il faut plussieur chose :
-> 1ér étape note tes objet comme seralisable (<Serializable()> en début de déclaration de tes structure/classe)
-> Sauvegarde d'un objet seralisable :
  -> ouvre un stream fichier (System.IO.FileStream)
  -> Cree un serialiseur (System.Runtime.Serialization.Formatters.Binary.BinaryFormatter)
  -> Ecit dans le fichier
-> Lecture d'un fichier serialisé
  -> ouvre un stream fichier (System.IO.FileStream)
  -> Cree un serialiseur (System.Runtime.Serialization.Formatters.Binary.BinaryFormatter) (Sa me rapel un truc )

De petit exemple VB.NET et strucure mais tres simple à traduire (fonctionement identique pour une classe):
Déclaration de la structure (ou classe)
<Serializable()> Public Structure S_ConfigGenerale
        Public DossierDonnees As String
        '[...]
    End Structure
Déclaration de l'objet à serialisé (rien de particulier en faite ici )
Public ConfigGenerale as S_ConfigGenerale

Fonction de sauvegarde :
Public Sub SauveConfig()
        Dim AccesseurAuFichier As New System.IO.FileStream("C:\NomDuFichierDeSauvegade.sav", IO.FileMode.OpenOrCreate)
        Dim Formateur As New System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
        Formateur.Serialize(AccesseurAuFichier, ConfigGenerale)
        AccesseurAuFichier.Close()
    End Sub

Fonction de lecture :
    Public Sub LoadConfig()
        Dim AccesseurAuFichier As New System.IO.FileStream("C:\NomDuFichierDeSauvegade.sav", IO.FileMode.Open)
        Dim Formateur As New System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
        ConfigGenerale = Formateur.Deserialize(AccesseurAuFichier)
        AccesseurAuFichier.Close()
    End Sub

Voila avec sa tu ne peut pas avoir encore des problèmes de serialisation (par contre à tu réelement cherché des tuto sur ce site av de possé cette question ??? Je suis sur que non, et c'est MAL !!!!! )

PS :
Tu peut serialisé plussieur objet dans le même ficheir.
Ex :
Public Sub SauveConfig()

        Dim AccesseurAuFichier As New System.IO.FileStream("C:\NomDuFichierDeSauvegade.sav", IO.FileMode.OpenOrCreate)

        Dim Formateur As New System.Runtime.Serialization.Formatters.Binary.BinaryFormatter

        Formateur.Serialize(AccesseurAuFichier, ConfigGenerale)
        Formateur.Serialize(AccesseurAuFichier, ConfigSpe)
        Formateur.Serialize(AccesseurAuFichier, ObjALaCon)

        AccesseurAuFichier.Close()

    End Sub

    Public Sub LoadConfig()

        Dim AccesseurAuFichier As New System.IO.FileStream("C:\NomDuFichierDeSauvegade.sav", IO.FileMode.Open)

        Dim Formateur As New System.Runtime.Serialization.Formatters.Binary.BinaryFormatter

        ConfigGenerale = Formateur.Deserialize(AccesseurAuFichier)
        ConfigSpe = Formateur.Deserialize(AccesseurAuFichier)

        ObjALaCon = Formateur.Deserialize(AccesseurAuFichier)


        AccesseurAuFichier.Close()

    End Sub

Dans ce cas ATTENTION aux obj. à nothing. A valider mais il me semble que sa posse des problèmes.

Bonne prog
Amicalement
Pensez "Réponse acceptée"
Commenter la réponse de Polack77
Messages postés
1100
Date d'inscription
mercredi 22 mars 2006
Statut
Membre
Dernière intervention
15 avril 2018
0
Merci
Et n'écris pas si GROS. Ton post est désagréable à lire du coup .

Amicalement
Pensez "Réponse acceptée"
Commenter la réponse de Polack77
Messages postés
1100
Date d'inscription
mercredi 22 mars 2006
Statut
Membre
Dernière intervention
15 avril 2018
0
Merci
Heeeeeee cela répond t'il à ta question ?
Si oui pense réponse acceptée (cela permettras à d'autre qui se pose la même question de trouvé la réponse plus facilement .
Si non te reste t'il des questions (sur le même sujet par contre ) ?

Tiens, je remarque que il n'y à pas de tuto sur la sérialisation dans cppfrance ????? Désolé pour ma remarque j'étais certain du contraire (mais une tite rechérche dans Google t'aurais permit de trouvé tout de suite , deux gros avantages : en générale les réponses sont plus précises et tu n'a pas à attendre d'éventuel réponse qui parfais n'arrive jamais en plus . J'ai recherché dans Google "sérialisation c#" et 1ér réponse : ici, ce tuto est même plus péris que ma réponse )

Amicalement
Pensez "Réponse acceptée"
Commenter la réponse de Polack77
Messages postés
10
Date d'inscription
jeudi 27 septembre 2007
Statut
Membre
Dernière intervention
9 décembre 2008
0
Merci
LoL.. Oui j'avais fait des recherches sur google et sur cppfrance avant de faire ce poste évidement..

Mais malheureusement comme je suis un bon gros débutant je n'ai rien trouvé d'assez claire pour y comprendre quelque chose.   C'est pourquoi j'ai créé ce poste, mais les exemples que tu me donnes en VB.NET et C# sont trop flous pour moi qui débute la programmation en C++. J'aurais besoin de quelque chose de plus claire et en C++...

Merci pour ton aide
Commenter la réponse de jex0519
Messages postés
1100
Date d'inscription
mercredi 22 mars 2006
Statut
Membre
Dernière intervention
15 avril 2018
0
Merci
Je n'es pas été claire
Haaaa......... Je vais faire mieux (déjà sa sera du C#, et du pas à pas)

Alors pour sérialisé un "truc" (objet, structure, ...) il faut plusieurs chose :
(1)
Déjà il faut que tu note tes class comme sérialisable (sa on ne peut pas faire autrement). Il siffi d'ajouté "<Serializable()>" à la déclaration de ta classe. ATTENTION il faut que tu l'ajoute à TOUTE les déclaration (normalement VisualStudio retourne une erreur si tu en oublie )

Exemple :
        [Serializable]
        class Personne
        {
//[...]
        }

        [Serializable]
        class Administrateur : Personne
        {
//[...]
        }

Tiens pk avais tu ajouté "public" dans ces déclarations ????

(2)
Il faut un "truc" qui te permet de lire/écrire dans un fichier. Pour cela on crée un objet "FileStream" (car c'est ce dont on à besoin pour la suite si non il existe aussi d'autre stream plus spécifique mais on ne les véra pas. C'est sans utilité ici)

Déclaration :
System.IO.FileStream AccesseurFichier;

Init de ton obj :
AccesseurFichier = new System.IO.FileStream("C:\\FichierSerialiser.dat",System.IO.FileMode.OpenOrCreate);

Pressions :
-> "C:\\FichierSerialiser.dat" est à remplacé par le nom du fichier dans le quel tu veut sauvegarder ton obj.
-> En C# les '\' doivent être doublé dans les chaine écrite en dur (soit direct dans le code prog).
-> Le mode d'ouverture correspond à ce que tu veut faire (ici ouvrir ou crée le fichier, on est plutôt dans un mode d'écriture du coup , pour lire il vaut mieux être en mode "System.IO.FileMode.Open" qui retourne une erreur si le fichier est abs, vue plus bas, pas de stress )

(3)
Ensuite il te faut un "truc" capable de transformé en une suite de nombre binaire l'objet que tu veut sérialisé. C'est la classe "BinaryFormatter" qui s'en charge (elle ne sait faire que sa, enfin je crois ). La même classe est utilisé pour re-transformé ta suite de valeur binaire en objet.

Déclaration :
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter Formatteur;

Init de l'obj :
Formatteur = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();

Utilisation en sérialisation (pour cela j'admét qu'un obj Admin basé sur la classe administrateur à été déclaré, on utilise un FileStream pour l'acces au fichier (2) ) :
Formatteur.Serialize(AccesseurFichier, Admin);

Utilisation en Déserialisation (toujour pour ce même obj Admin) :
Admin = Formatter.Deserialize(AccesseurFichier);

Fin
Voila déjà on à passé en revue toute les spé

Maintenant un Exemple :
Fonction d'écriture de deux obj dans un fichier (Admin et Perso) :
public Boolean SauveObjDansFichier (string
CheminFichier
,Administrateur Admin,Personne Perso)
        {
            System.Runtime.Serialization.Formatters.Binary.BinaryFormatter Formatteur;
            System.IO.FileStream AccesseurFichier = null;
            try //<- Démarage de la gestion d'erreur (même si ici aucune erreur ne devrais se produire, sauf si par exemple on demande de crée en fichier en "g:" et que ce lecteur n'existe pas)
            {
                AccesseurFichier = new System.IO.FileStream(
CheminFichier
, System.IO.FileMode.OpenOrCreate); //ici OpenOrCreate car on écrit donc si le fichier n'existe pas on le cré
                Formatteur.Serialize(AccesseurFichier, Admin);
                Formatteur.Serialize(AccesseurFichier, perso);
                AccesseurFichier.Close(); //Fini plus qu'à fermer le ficheir ;)
                AccesseurFichier = null;
                return true;
            }
            catch (Exception) //<- Le code passe ici en cas d'erreur
            {
                if (AccesseurFichier != null) //<- Si le fichier est encore ouvert on le ferme 
(si non sa pourais possé des problèmes pour plus tard)

                {
                    AccesseurFichier.Close;
                }
                return false;
                throw;
            }

Fonction de lecture de ces même obj :
public Boolean LoadObjDepuisFichier(string CheminFichier, ref Administrateur Admin,ref Personne Perso)
        {
            System.Runtime.Serialization.Formatters.Binary.BinaryFormatter Formatteur;
            System.IO.FileStream AccesseurFichier = null;
            try //<- Démarage de la gestion d'erreur
            {
                AccesseurFichier = new System.IO.FileStream(
CheminFichier
, System.IO.FileMode.Open); //Ici open car on lit donc on ne veut pas crée de fichier si il n'existe pas ;)
                &Admin = Formatteur.Deserialize (AccesseurFichier);
                &Perso = Formatteur.Deserialize (AccesseurFichier);
                AccesseurFichier.Close(); //Fini plus qu'à fermer le ficheir ;)
                AccesseurFichier = null;
                return true;
            }
            catch (Exception) //<- Le code passe ici en cas d'erreur (le fichier n'existe pas par exemple)
            {
                if (AccesseurFichier != null) //<- Si le fichier est ouvert on le ferme (si non sa pourais possé des problèmes pour plus tard)
                {
                    AccesseurFichier.Close;
                }
                return false;
                throw;
            }
        }

Une petite présision pour cette fonction :
Cette fonction (Load...) utilise un passage par référance ce qui veut dire que si tu modifie Admin alors c'est en faite la variable passé que se voie modifier (identique à ByRef en VB.NET)

Voila je ne voie pas comment être plus claire si un point précis te pose encore problème demande je n'aurais plus le temps de refaire un truc complet

Bonne prog
Amicalement
Pensez "Réponse acceptée"
Commenter la réponse de Polack77
Messages postés
1100
Date d'inscription
mercredi 22 mars 2006
Statut
Membre
Dernière intervention
15 avril 2018
0
Merci
Oups un oublie de trad du VB.NET au C# il faut lire :
Déjà il faut que tu note tes class comme sérialisable (sa on ne peut pas faire autrement). Il siffi d'ajouté "[Serializable]" à ...

Et non
Déjà il faut que tu note tes class comme sérialisable (sa on ne peut pas faire autrement). Il siffi d'ajouté "<Serializable()>" à ...

Dzl

Amicalement
Pensez "Réponse acceptée"
Commenter la réponse de Polack77
Messages postés
1100
Date d'inscription
mercredi 22 mars 2006
Statut
Membre
Dernière intervention
15 avril 2018
0
Merci
Re-oups bug à la ligne :
Formatteur.Serialize(AccesseurFichier, perso);
Le C# (comme le C) est sensible à la casse donc il faut :

Formatteur.Serialize(AccesseurFichier, Perso);

Amicalement
Pensez "Réponse acceptée"
Commenter la réponse de Polack77
Messages postés
1100
Date d'inscription
mercredi 22 mars 2006
Statut
Membre
Dernière intervention
15 avril 2018
0
Merci
Oupsssssssssssss tu veut du C++ et non pas du C#
Je ne sait pas faire en C++ (je ne sait même pas si c'est possible je ne l'es jamais fait )

A l'époque je sauvegardais mes données dans des fichier ini en utilisant les API windows
Je ne peut que t'envoiler là :
http://www.cppfrance.com/code.aspx?ID=9349

Amicalement
Pensez "Réponse acceptée"
Commenter la réponse de Polack77
Messages postés
1100
Date d'inscription
mercredi 22 mars 2006
Statut
Membre
Dernière intervention
15 avril 2018
0
Merci
Décidément c'est ma journée des oublies :
Si non tu à la possibilité de récup une version de Visual Stuido 2008 la :
http://msdn.microsoft.com/fr-fr/express/aa975050.aspx
Normalement il est compatible au C++ et devrais pouvoir convertir automatiquement ton projet (je dit bien logiquement ce n'es pas parfait non plus, hélasse )

Amicalement
Pensez "Réponse acceptée"
Commenter la réponse de Polack77
Messages postés
1100
Date d'inscription
mercredi 22 mars 2006
Statut
Membre
Dernière intervention
15 avril 2018
0
Merci
Si non il semblerais que ces lients est aidé des personne à faire sa en C++ :
http://www.cplusplus.com/reference/iostream/ostream/write.html
http://www.boost.org/doc/libs/1_35_0/libs/serialization/doc/index.html

Si non sa devrais être possible en utilisant des tableau binaire que tu gére toi même :
Tu récup la taille de ton obj A L'OCTET PRÉS
Tu récup l'adresse de départ de ton obj (sa c'est facile ajoute simplement & avant le nom de ta variable)
De la tu traite sa comme une chaine de carac (Par contre ATTENTION si des octect sont à 0 alors les fonction tel que strcpy ne fonctionneront pas IL FAUT que tu utilise des fonction qui prenne en conte le nombre d'oct que tu envoie)
Ensuite tu écrit sa dans un fichier tél quel. Puis pour la lecture tu lit le fichier AU COMPLET et copie la valeur mémoire à l'adresse de ton obj (avec memecpy). Par contre tu devrais toi même gérer l'ensemble des erreurs éventuel, les versions de tes objet, la validité des données pour l'objet qui dois les recevoir ext si non de GROSSE surprise t'attende.

Si tu est débutant je te conseil vivement soit
-> de passé en C# si tu tiens à la sérialisation
-> de sauvegarder tes données dans des ".ini" (avec la notion de section et la possibilité de crée plusieurs fichiers si tu te débrouille bien c'est vraiment plus efficace que sa n'en à l'aire)
Commenter la réponse de Polack77
Messages postés
1100
Date d'inscription
mercredi 22 mars 2006
Statut
Membre
Dernière intervention
15 avril 2018
0
Merci
LOL
memcpy pas memecpy (copie de ma mémé MDR )

Amicalement
Pensez "Réponse acceptée"
Commenter la réponse de Polack77
Messages postés
10
Date d'inscription
jeudi 27 septembre 2007
Statut
Membre
Dernière intervention
9 décembre 2008
0
Merci
MDR Merci pour ce petit cours rapide de C# , malheureusement je suis étudiant et c'est un projet en C++ (dévellopé sous dev-cpp et Qt designer) donc je n'ai pas le choix du langage..




Je dois pouvoir sauvegarder des objets afin de les récupérer par la suite a l'ouverture du programme.

Je pensais que la méthode la plus simple était la sériallisation (car je l'ai utilisée en java) mais apparament en C++ il y a d'autres possibilitées et je ne sais pas laquelle est la mieux adaptée....

Je vais me renseigner sur les fichiers .ini et voir si c'est faisable...

Je ne suis pas au bout de mes peines je crois lol

Merci de tout le mal que tu t'es donnés quand même en tout cas
Commenter la réponse de jex0519
Messages postés
1100
Date d'inscription
mercredi 22 mars 2006
Statut
Membre
Dernière intervention
15 avril 2018
0
Merci
Juste une petite question : Quel quantité de données ~ à tu à sauvegardé ?
Si juste des configurations : fichier ini parfaitement adapté (enfin de mon point de vue).
De grosse données : tu à le dois aux base de données (si oui je pense que sa peut être bien, rapide à faire, et relativement "classieux" pour ton rendu de projet , jette un coup d'œil ici le sql c'est le langage base de données) ?
Les deux : Les deux ?

Amicalement
Pensez "Réponse acceptée"
Commenter la réponse de Polack77
Messages postés
10
Date d'inscription
jeudi 27 septembre 2007
Statut
Membre
Dernière intervention
9 décembre 2008
0
Merci
La quantité de donnée n'est pas gigantesque et malheureusement le délai du projet ne me laisse pas le temps de m'interessé en plus au SQL déjà que Qt designer est assez complexe...

Je vais voir s'il est possible de sauvegarder mes objets, vectors et etc à l'aide des fichiers ini...
Commenter la réponse de jex0519
Messages postés
1100
Date d'inscription
mercredi 22 mars 2006
Statut
Membre
Dernière intervention
15 avril 2018
0
Merci
Ok pas de problème. Tu tu change d'avis et que tu ne t'en sort pas post sur "http://www.sqlfr.com/" et envoie moi un MP je te filerais un ou deux tuyaux

Amicalement
Pensez "Réponse acceptée"
Commenter la réponse de Polack77
Messages postés
1100
Date d'inscription
mercredi 22 mars 2006
Statut
Membre
Dernière intervention
15 avril 2018
0
Merci
Je viens de pensé à un petit truc :
   Les fichier ini (surtout avec les deux API que je t'es indiqué) on des problèmes pour stocker certaine valeur (surtout en cas de conversion de valeur numérique en chaine (prob de '\0') mais aussi avec les retour charriots). Pour contourné ce/s problème/s perso je passais par Base64.
[lien wiki lien wiki ]

Si tu fait le choix de tout stocké en ini je te conseil de passé systématiquement par ce genre de codage (pas forcément celui ci d'autre tout aussi adapté doivent existé) sa ne coute pas grand choses (en temps de traitement en tout cas, et l'espace disque ne coute plus très chère aujourd'hui). Par contre ATTENTION stockage non optimisé en taille les examinateurs pourraient être regardant la dessus (et du coup chiant ^^) à ton rendu de projet.

Fait également attention aux sorties de ta fonction Base64 (surtout si tu en récup une toute faite) des retours charriot son automatiquement inséré (ceux si n'ont aucune signification pour la re-traduction, donc supprime les purement et simplement, les ini ne supporte pas les retour charriots)

Amicalement
Pensez "Réponse acceptée"
Commenter la réponse de Polack77
Messages postés
1100
Date d'inscription
mercredi 22 mars 2006
Statut
Membre
Dernière intervention
15 avril 2018
0
Merci
N'hésite surtout pas à me faire un petit fet-back je pourrais peut être de données encore un ou deux conseil (pas forcément bon mais c'est pas grave tu feras le trie mdr).
A la rigueur crée un nouveau sujet dans le thème "Le bar / discutions libre"

Bonne prog (et bon courage pour ton projet c'est pas simple j'ai connue )

Amicalement
Pensez "Réponse acceptée"
Commenter la réponse de Polack77