begin process at 2013 05 22 11:42:37
  Trouver un code source :
 
dans
 
Accueil > 

Tutoriels

 > 

Astuces

 > SAUVEGARDE BINAIRE D'UN OBJET C++

SAUVEGARDE BINAIRE D'UN OBJET C++


 Information sur le tutoriel

Note :
Aucune note

 Description

Ce tutoriel explique comment enregistrer l'instance d'une classe sans à avoir à enregistrer toutes les variables.
Cette méthode est mise en pratique dans un exemple d'une classe "Personnage", qui contient elle-même ses méthodes de sauvegarde et de lecture.

Tutorial

SAUVEGARDE BINAIRE D’UNE INSTANCE DE CLASSE EN C++ (Pop70)



PRINCIPE :


Dans beaucoup de programmes, il peut être utile lors de l’exécution d’enregistrer un objet.


Pour faire ceci, au lieu de sauvegarder chacune des variables, on utilise l’une des méthodes de fstream : write.


Son prototype est ostream& write ( const char* s , streamsize n );


Le premier argument est une chaine de caractère (qui sera l’objet), et le deuxième, la taille de l’objet.


Pour la lecture on utilise la méthode read : istream& read ( char* s, streamsize n );



Pour enregistrer un objet, il suffit alors de faire :


Code c++ :



#include <fstream>


ofstream Fichier (chemin, ios ::binary); /* (le paramètre binary,

indispensable ici, peut-être refusé par certain compilateur, toutefois il fonctionne

parfaitement sur Code ::Blocks).*/


if ( !Fichier)

{

return ;

}


Fichier.write ((char*)&objet, sizeof(objet)) ;


// ...


Fichier.read((char*) &objet, sizeof(objet));





UN EXEMPLE :


Ici, on va utiliser cette méthode sur une classe Personnage.

Les personnages auront un nom (std ::string wNom), un age (unsigned short wAge) et des points de vie (unsigned short wVie).


Il y aura 3 fichiers :

-main.cpp

-Personnage.hpp

-Personnage.cpp



On va commencer par le main.cpp :




Code C++ :




#include <iostream>

#include "Personnage.hpp"


int main()

{

// CREATION D'UN OBJET PERSONNAGE :


Personnage *John = new Personnage;


// LECTURE DE L'OBJET


std::cout << "Creation d'un personnage : \n";

std::cout << *John;


// MODIFICATION DE L'OBJET


std::string nom = "John Bazq";

John->SetNom(nom);

John->SetAge (35);

John->SetVie (70);


// LECTURE DE L'OBJET


std::cout << "Personnage defini : \n";

std::cout << *John;


// ENREGISTREMENT DE L'OBJET


John->Enregistrer ("JOHN");


// SUPRESSION DE L'OBJET


delete John;


// CREATION DE L'OBJET



std::cout << "Creation d'un personnage : \n";

John = new Personnage;


// LECTURE DE L'OBJET


std::cout << *John;


// MODIFICATION A PARTIR DU FICHIER


John->Lire ("JOHN");


// LECTURE DE L'OBJET


std::cout << "Personnage du fichier : \n";

std::cout << *John;



system ("PAUSE");

return EXIT_SUCCESS;

}





Ensuite on va créer Personnage.hpp, et lui donner toutes les méthodes nécessaires à l’exécution du main.


Il va donc lui falloir les méthodes (publiques) :


void SetNom(std::string &);

std::string GetNom() const;


void SetAge (unsigned short);

unsigned short GetAge () const;


void SetVie (unsigned short);

unsigned short GetVie () const;


void Enregistrer (std::string) const;

void Lire (std::string);


friend std::ostream& operator<< (std::ostream&, Personnage&);


Plus les constructeurs :

Personnage();

~Personnage() ;


Et les variables membres (privées) énoncées précédemment :


std::string wNom;

unsigned short wAge;

unsigned short wVie;



Il faut aussi penser à protéger le header des inclusions multiples.


    On obtient donc :



Code C++ :



#ifndef DEF_PERSONNAGE_HPP

#define DEF_PERSONNAGE_HPP


#include <iostream>

#include <fstream>


class Personnage

{

public:


Personnage();

~Personnage();


void SetNom(std::string &);

std::string GetNom() const;


void SetAge (unsigned short);

unsigned short GetAge () const;


void SetVie (unsigned short);

unsigned short GetVie () const;


void Enregistrer (std::string) const;

void Lire (std::string);


friend std::ostream& operator<< (std::ostream&, Personnage&);



private:


std::string wNom;

unsigned short wAge;

unsigned short wVie;


};



#endif




Pour finir, on va implémenter cette classe dans Personnage.cpp.

On commence par les méthodes basiques de modifications et d’accessions, en vérifiant les valeurs entrantes et les exceptions.



Le constructeur et le destructeur :


Personnage::Personnage()

{

wNom = "Aucun_nom";

wAge = 20;

wVie = 100;

}




Personnage::~Personnage()

{


}



La méthode de modification du nom :


void

Personnage::SetNom(std::string &Nom)

{

try

{

if (Nom == "")

throw "La chaine de caractere est vide !";

if (Nom.size() > 40)

throw "Nom trop long !";


wNom = Nom;

}

catch (const char *exception)

{

std::cerr << "\n*** " << exception << " ***\n";

}

catch (...)

{

std::cerr << "\n*** Une erreur s'est produite ! ***\n";

}

}


La méthode d’accès du nom :


std::string

Personnage::GetNom()

const

{

return wNom;

}


La méthode de modification de l’âge :


void

Personnage::SetAge (unsigned short Age)

{

try

{

if (Age > 137)

throw "L'age est trop grand !";


wAge = Age;

}

catch (const char *exception)

{

std::cerr << "\n*** " << exception << " ***\n";

}

catch (...)

{

std::cerr << "\n*** Une erreur s'est produite ! ***\n";

}


}



La méthode d’accès de l’âge :


unsigned short

Personnage::GetAge ()

const

{

return wAge;

}


La méthode de modification de la vie :


void

Personnage::SetVie (unsigned short Vie)

{

try

{

if (Vie > 100)

throw "Il y a trop de points de vie !";


wVie = Vie;

}

catch (const char *exception)

{

std::cerr << "\n*** " << exception << " ***\n";

}

catch (...)

{

std::cerr << "\n*** Une erreur s'est produite ! ***\n";

}

}


La méthode d’accès de la vie :


unsigned short

Personnage::GetVie ()

const

{

return wVie;

}



    

    Vient ensuite la méthode d’enregistrement.


Sur le principe : Fichier.write ((char*)&objet, sizeof(objet)) ;

La méthode se trouvant dans la classe devient :

Fichier.write ((char*)this, sizeof(*this)) ;



On peut donc implémenter notre méthode Enregistrer sous cette forme :



void

Personnage::Enregistrer (std::string Chemin)

const

{

try

{

if (Chemin == "")

throw "Chemin vide !";

if (Chemin.size() > 300)

throw "Chemin trop long";


std::ofstream fichier_sortant (Chemin.c_str(), std::ios::binary);

if (!fichier_sortant)

{

std::cerr << "\a\n\nImpossible de creer le fichier de sauvegarde\n\n";

return;

}

fichier_sortant.write ((char*) this, sizeof (*this));

fichier_sortant.close();

}

catch (const char *exception)

{

std::cerr << "\n*** " << exception << " ***\n";

}

catch (...)

{

std::cerr << "\n*** Une erreur s'est produite ! ***\n";

}

}




    Vient ensuite la lecture du fichier :


Sur le même principe : Fichier.read((char*) &objet, sizeof(objet));

     devient : Fichier.read((char*) this, sizeof(*this));


La méthode finale :


void

Personnage::Lire (std::string Chemin)

{

try

{

if (Chemin == "")

throw "Chemin vide !";

if (Chemin.size() > 300)

throw "Chemin trop long";

std::ifstream fichier_entrant(Chemin.c_str(), std::ios::binary);

if (!fichier_entrant)

{

std::cerr << "\a\n\nImpossible de lire le fichier de sauvegarde\n\n";

return;

}

fichier_entrant.read((char*) this, sizeof(*this));

fichier_entrant.close();

}

catch (const char *exception)

{

std::cerr << "\n*** " << exception << " ***\n";

}

catch (...)

{

std::cerr << "\n*** Une erreur s'est produite ! ***\n";

}

}



Sans oublier d’implémenter la surcharge de l’opérateur << :


std::ostream& operator<< (std::ostream &Flux, Personnage &rhs)

{

try

{


Flux << "\nNom du personnage : " << rhs.GetNom()

<< "\nAge du personnage : " << rhs.GetAge()

<< "\nVie restante du personnage : " << rhs.GetVie()

<< "\n\n";

return Flux;

}

catch (...)

{

std::cerr << "\n*** Une erreur s'est produite ! ***\n";

}

}




Le code source final :


Code C++ :



#include "Personnage.hpp"


Personnage::Personnage()

{

wNom = "Aucun_nom";

wAge = 20;

wVie = 100;

}



Personnage::~Personnage()

{


}



void

Personnage::SetNom(std::string &Nom)

{

try

{

if (Nom == "")

throw "La chaine de caractere est vide !";

if (Nom.size() > 40)

throw "Nom trop long !";


wNom = Nom;

}

catch (const char *exception)

{

std::cerr << "\n*** " << exception << " ***\n";

}

catch (...)

{

std::cerr << "\n*** Une erreur s'est produite ! ***\n";

}

}



std::string

Personnage::GetNom()

const

{

return wNom;

}



void

Personnage::SetAge (unsigned short Age)

{

try

{

if (Age > 137)

throw "L'age est trop grand !";


wAge = Age;

}

catch (const char *exception)

{

std::cerr << "\n*** " << exception << " ***\n";

}

catch (...)

{

std::cerr << "\n*** Une erreur s'est produite ! ***\n";

}


}



unsigned short

Personnage::GetAge ()

const

{

return wAge;

}



void

Personnage::SetVie (unsigned short Vie)

{

try

{

if (Vie > 100)

throw "Il y a trop de points de vie !";


wVie = Vie;

}

catch (const char *exception)

{

std::cerr << "\n*** " << exception << " ***\n";

}

catch (...)

{

std::cerr << "\n*** Une erreur s'est produite ! ***\n";

}

}



unsigned short

Personnage::GetVie ()

const

{

return wVie;

}



void

Personnage::Enregistrer (std::string Chemin)

const

{

try

{

if (Chemin == "")

throw "Chemin vide !";

if (Chemin.size() > 300)

throw "Chemin trop long";


std::ofstream fichier_sortant (Chemin.c_str(), std::ios::binary);

if (!fichier_sortant)

{

std::cerr << "\a\n\nImpossible de creer le fichier de sauvegarde\n\n";

return;

}

fichier_sortant.write ((char*) this, sizeof (*this));

fichier_sortant.close();

}

catch (const char *exception)

{

std::cerr << "\n*** " << exception << " ***\n";

}

catch (...)

{

std::cerr << "\n*** Une erreur s'est produite ! ***\n";

}

}



void

Personnage::Lire (std::string Chemin)

{

try

{

if (Chemin == "")

throw "Chemin vide !";

if (Chemin.size() > 300)

throw "Chemin trop long";

std::ifstream fichier_entrant(Chemin.c_str(), std::ios::binary);

if (!fichier_entrant)

{

std::cerr << "\a\n\nImpossible de lire le fichier de sauvegarde\n\n";

return;

}

fichier_entrant.read((char*) this, sizeof(*this));

fichier_entrant.close();

}

catch (const char *exception)

{

std::cerr << "\n*** " << exception << " ***\n";

}

catch (...)

{

std::cerr << "\n*** Une erreur s'est produite ! ***\n";

}

}



std::ostream& operator<< (std::ostream &Flux, Personnage &rhs)

{

try

{


Flux << "\nNom du personnage : " << rhs.GetNom()

<< "\nAge du personnage : " << rhs.GetAge()

<< "\nVie restante du personnage : " << rhs.GetVie()

<< "\n\n";

return Flux;

}

catch (...)

{

std::cerr << "\n*** Une erreur s'est produite ! ***\n";

}

}







Et voilà ce qu’affiche la console lors de l’exécution :




Et c’est ainsi que s’achève ce petit tuto….J’espère que ce tutoriel vous aura été, et vous sera utile.


(Remonter)

 Historique

28 mai 2011 14:28:46 :
Correction de fautes.

Commentaires

Commentaire de Romano58 le 07/07/2011 16:37:21

Vraiment très instructif! En faite, c'est en quelques sorte l'équivalent de la sérialisation en java si j'ai bien compris...
Bravo, super tuto.

 Ajouter un commentaire




Nos sponsors


Sondage...

CalendriCode

Mai 2013
LMMJVSD
  12345
6789101112
13141516171819
20212223242526
2728293031  

Consulter la suite du CalendriCode

Photothèque

A découvrir



 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 0,499 sec (3)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales