148 votes

Est-il possible de sérialiser et désérialiser une classe en C++?

Est-il possible de sérialiser et désérialiser une classe en C++?

J'ai été en utilisant Java, depuis maintenant 3 ans, et la sérialisation / désérialisation est assez banale dans cette langue. Est-ce que C++ ont des caractéristiques similaires? Existe-il des bibliothèques natives que gérer la sérialisation?

Un exemple serait utile.

98voto

Head Geek Points 10874

Le Boost::serialization bibliothèque gère plutôt élégante. Je l'ai utilisé dans plusieurs projets.

EDIT 1: Il y a un programme d'exemple montrant comment l'utiliser, ici.

EDIT 2: Le seul natif de façon de le faire est d'utiliser les flux. C'est pratiquement tous les Boost::serialization de la bibliothèque, il s'étend sur le ruisseau de la méthode par la mise en place d'un cadre pour écrire des objets dans un texte de format et de les lire à partir du même format. Pour les types intégrés, ou vos propres types avec operator<< et operator>> bien définie, c'est assez simple, voir le C++ FAQ Lite pour plus d'informations.

56voto

Azoth Points 541

Je me rends compte que c'est un vieux post, mais c'est l'un des premiers qui vient lors d'une recherche d' c++ serialization.

J'encourage tout le monde qui a accès à C++11 pour prendre un coup d'oeil à céréales, un C++11 en-tête uniquement de la bibliothèque pour la sérialisation binaire qui prend en charge, JSON et XML hors de la boîte. de céréales a été conçu pour être facile à développer et à utiliser et a une syntaxe similaire à renforcer.

17voto

Frank Krueger Points 27508

Boost est une bonne suggestion. Mais si vous souhaitez lancer votre propre, il n'est pas difficile.

Fondamentalement, vous avez juste besoin d'un moyen de construire un graphe d'objets et de sortie à certains structuré format de stockage (JSON, XML, YAML, peu importe). La construction du graphe est aussi simple que l'utilisation d'un marquage récursive décent de l'objet de l'algorithme puis la sortie de toutes les marqués objets.

J'ai écrit un article décrivant un rudimentaire (mais puissant) sérialisation système. Vous trouverez peut-être intéressant: Utilisez SQLite comme un disque de Format de Fichier, Partie 2.

15voto

yoav.aviram Points 1014

Je recommande Google protocol buffers. J'ai eu la chance de faire l'essai routier de la bibliothèque sur un nouveau projet et il est remarquablement facile à utiliser. La bibliothèque est fortement optimisé pour les performances.

Protobuf est différent des autres solutions de sérialisation mentionné ici dans le sens qu'il n'est pas sérialiser vos objets, mais plutôt génère du code pour les objets qui sont de la sérialisation en fonction de votre cahier des charges.

14voto

M2tM Points 2145

Je recommande fortement d'utiliser Boost::serialization comme la plupart des gens suggèrent ici. J'ai, cependant, écrit un jouet exemple pour un ami qui était curieux de savoir comment vous le feriez sans coup de pouce. Je vais juste coller le programme complet ici.

Il ne gère pas la profondeur de la copie, ou la reconstitution de références, ou de l'une de ces autres considérations que vous auriez de puzzle (qui Boost::serialization a déjà fait).

Parce que c'est un jouet projet que je viens de faire les choses publiques. Vous voulez avoir l'encapsulation dans vos classes réelles qui peuvent exiger que les demandes d'amitié exploitants et de fournir la bonne accesseurs aux membres internes.

Sérialiser/Désérialiser Exemple

#include <iostream>
#include <sstream>
#include <vector>
#include <string>

struct Contents {
    int id;
    char chr;

    Contents(int id, char chr):id(id),chr(chr){}
};

std::ostream& operator<<(std::ostream &out, const Contents &me){
    out << "Id: " << me.id << " Chr: " << me.chr;
    return out;
}

typedef Contents Container_Value_Type;
const Container_Value_Type defaultBad = Contents(-1, '!');
const size_t Container_Vector_Size = 4;

struct Container{
    std::vector<Container_Value_Type> data;

    Container():data(Container_Vector_Size, defaultBad){}

    void serialize( std::ostream &stream ) const {
        for( size_t i = 0; i < Container_Vector_Size; ++i){
            stream.write( reinterpret_cast <const char*> ( &data[i] ), sizeof( Container_Value_Type ) ); 
        }
    }
    void deserialize( std::istream &stream ) {
        data.clear();
        std::vector<char> buffer(sizeof(Container_Value_Type));
        for( size_t i = 0; i < Container_Vector_Size; ++i){
            stream.read(&buffer[0], sizeof(Container_Value_Type));
            data.push_back(*reinterpret_cast<Container_Value_Type*>(&buffer[0]));
        }
    }
};

std::stringbuf& operator<<(std::stringbuf &stream, Container &me) {
    std::istream ibuffer(&stream);
    me.deserialize(ibuffer);
    return stream;
}

std::stringbuf& operator>>(std::stringbuf &stream, const Container &me) {
    std::ostream obuffer(&stream);
    me.serialize(obuffer);
    return stream;
}

std::ostream& operator<<(std::ostream &stream, const Container &me) {
    stream << "Container {" << std::endl;
    for( size_t i = 0; i < Container_Vector_Size; ++i){
        stream << i << ": " << me.data[i] << std::endl;
    }
    stream << "}" << std::endl << std::endl;
    return stream;
}

int main(){
    Container start;
    start.data[0].id = 1;
    start.data[0].chr = 'a';

    start.data[1].id = 2;
    start.data[1].chr = 'b';

    start.data[2].id = 3;
    start.data[2].chr = 'c';

    start.data[3].id = 4;
    start.data[3].chr = 'd';

    Container reached;
    std::stringbuf buffer;
    buffer >> start;
    buffer << reached;


    std::cout << start;
    std::cout << reached;
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X