2011-03-03 11 views
10

Sono nuovo di boost e C++ e sto tentando di serializzare un oggetto in binario e quindi di non serializzarlo.C++ incrementare la serializzazione con stringstream

sto utilizzando le classi dalla esempio: http://en.highscore.de/cpp/boost/serialization.html

Quindi suppongo che questo è la classe che sto cercando di serializzare:

class person 
{ 
public: 
    person() { } 

    person(int age) : age_(age) { } 

    int age() const { return age_; } 

private: 
    friend class boost::serialization::access; 

    template <typename Archive> 
    void serialize(Archive &ar, const unsigned int version) 
    { 
    ar & age_; 
    } 

    int age_; 
}; 

Questo è il codice di serializzazione:

const char * save(Object ss) 
{ 
    boost::archive::binary_oarchive oa(ss); 
    person p(31); 
    oa << p; 

    return ss.str().data(); 
} 

Questo è il codice di unserialization:

void load(const char * str) 
    { 

     stringstream s; 
     s << str; 

     boost::archive::binary_iarchive ia(s); 
     person p; 
     ia >> p; 
     std::cout << p.age() << std::endl; 

    } 

Quando si tenta di eseguire questo codice, ricevo questo errore:

terminate called after throwing an instance of 'boost::archive::archive_exception' 
    what(): stream error 

Il che mi porta a chiedere, c'è un modo corretto di fare questo?

Grazie, molto apprezzato.

EDIT: Questa versione funziona:

Questo è il codice di serializzazione:

string save() 
{ 
    boost::archive::binary_oarchive oa(ss); 
    person p(31); 
    oa << p; 

    return ss.str(); 
} 

Questo è il codice di deserializzazione:

void load(string str) 
    { 

     stringstream s; 
     s << str; 

     boost::archive::binary_iarchive ia(s); 
     person p; 
     ia >> p; 
     std::cout << p.age() << std::endl; 

    } 

EDIT2: Questa versione non funziona. Gradirei commenti su una correzione. Grazie.

void Serialization::save() 
{ 
    stringstream ss; 
    { 
     boost::archive::binary_oarchive oa(ss); 
     person p(31); 
     oa << p; 
    } 


     const char * temp1 = ss.str().data(); 

     stringstream s; 
     s << temp1; 

     cout << "UNSERIALIZING\n"; 
     boost::archive::binary_iarchive ia(s); 
     person p1; 
     ia >> p1; 
     std::cout << p1.age() << std::endl; 

} 

risposta

10

L'utilizzo di archivi binari con std::stringstream è consentito, poiché qualsiasi carattere può essere memorizzato in un std::stringstream/std::string.

Il problema è il passaggio dei dati risultanti come una stringa C terminata da null, poiché è altamente probabile che i dati binari abbiano valori nulli incorporati, pertanto in seguito al caricamento i dati verranno troncati. Inoltre, la funzione di salvataggio sta restituendo i dati che puntano in un oggetto distrutto, invocando undefined behavior.

+0

Grazie per il commento. Puoi approfondire "i dati che puntano su un oggetto distrutto"? Ho assunto che i dati vengano distrutti quando la funzione termina. Quindi ho restituito i dati const char * prima che la funzione fosse terminata e l'ho archiviata in una variabile esterna save(), quindi l'ho passata a load(). Sto indovinando che la mia logica è sbagliata dal momento che gli errori del programma. – user459811

+1

Il puntatore restituito da 'std :: string :: data()' è valido solo fino a quando la 'stringa' non viene modificata o distrutta. La 'stringa' restituita da' std :: stringstream :: str() 'viene distrutta al completamento dell'istruzione' return'. Quindi chiunque chiami la funzione 'save' otterrà un puntatore a dati non validi il 100% delle volte. – ildjarn

+0

Ah capisco. Puoi consigliare un approccio migliore o un modo per aggirare i dati senza incorporare valori null? – user459811

-2

Non è possibile utilizzare binary_iarchive/binary_oarchive con stringstream, perché alcuni caratteri 'binari' non sono ammessi all'interno di una 'stringa'. Se si desidera utilizzare stringstream, è necessario "text_iarchive/text_oarchive" o "xml_iarchive/xml_oarchive".

Con 'binary_ {io} archive' (prestazioni) è necessario utilizzare un 'fstream'.

+0

Grazie per il commento. Ho modificato il mio codice in modo tale che non usi più la stringa ma const char * invece che possa ancora utilizzare un stringstream. Tuttavia, mi sta ancora dando errori. Ogni punto nella giusta direzione è molto apprezzato. Grazie. – user459811

+7

I caratteri "binari" sono effettivamente ammessi all'interno di 'std :: string's. Ditelo con me - un 'char' è un' char' è un 'char', non c'è differenza tra 'binary' e 'text' oltre al contesto. – ildjarn