Sto usando la libreria Boost serializzazione, che è in realtà piuttosto bello, e mi permette di fare involucri semplici per salvare i miei oggetti serializzabili in stringhe, in questo modo:Come collegare la serializzazione Boost e iostreams per serializzare e gzip un oggetto in stringa?
namespace bar = boost::archive;
namespace bio = boost::iostreams;
template <class T> inline std::string saveString(const T & o) {
std::ostringstream oss;
bar::binary_oarchive oa(oss);
oa << o;
return oss.str();
}
template <class T> inline void saveFile(const T & o, const char* fname) {
std::ofstream ofs(fname, std::ios::out|std::ios::binary|std::ios::trunc);
bar::binary_oarchive oa(ofs);
oa << o;
}
template <class T> inline void loadFile(T & o, const char* fname) {
std::ifstream ifs(fname, std::ios::in|std::ios::binary);
assert(ifs.good()); // XXX catch if file not found
bar::binary_iarchive ia(ifs);
ia >> o;
}
Il fatto è che ho appena trovato il ho bisogno di comprimere anche i miei dati serializzati, quindi sto cercando di farlo con i filtri in boost :: iostreams. Ho capito come farlo con successo con i file:
template <class T> inline void saveGZFile(const T & o, const char* fname) {
std::ofstream ofs(fname, std::ios::out|std::ios::binary|std::ios::trunc);
bio::filtering_streambuf<bio::output> out;
out.push(boost::iostreams::gzip_compressor());
out.push(ofs);
bar::binary_oarchive oa(out);
oa << o;
}
template <class T> inline void loadGZFile(T & o, const char* fname) {
std::ifstream ifs(fname, std::ios::in|std::ios::binary);
assert(ifs.good()); // XXX catch if file not found
bio::filtering_streambuf<bio::input> in;
in.push(bio::gzip_decompressor());
in.push(ifs);
bar::binary_iarchive ia(in);
ia >> o;
}
Ma non riesco a capire come salvare correttamente in una stringa compressa. Il problema è che non sto scaricando la catena dei filtri, ma ho provato a scoppiare e sincronizzare e nulla sembra funzionare. Ecco il mio codice di rotta:
template <class T> inline std::string saveGZString(const T & o) {
std::ostringstream oss;
bio::filtering_streambuf<bio::output> out;
out.push(bio::gzip_compressor());
out.push(oss);
bar::binary_oarchive oa(out);
oa << o;
// XXX out.pop() twice? out.strict_sync()?? oss.flush()??
return oss.str();
}
Di conseguenza alcuni dati rimane incastrato nel buffer di flusso da qualche parte, e finisco sempre con aa pochi isolati completi (16K o 32K) di dati compressi, quando so che dovrebbe essere 43K o così dato l'output (valido) che ottengo dall'usare il mio metodo saveGZFile. Apparentemente collegando l'ofstream si chiude e si svuota in modo corretto, ma non aggancia lo stringstream.
Qualsiasi aiuto? (Questa è la mia prima domanda StackOverflow - aiutami, ragazzi, siete la mia unica speranza!)
È possibile evitare il trucco di limitazione dell'ambito con una chiamata a flush(). f.flush() –
nel codice non funzionante nella mia domanda, il commento dice "' oss.flush() ?? "" perché chiamare 'flush()' su 'ostringstream' non funzionava. il trucco di limitazione dell'ambito è l'unica cosa che ha funzionato per me. a meno che tu non voglia dire che dovrei scaricare 'f', che non ha un metodo flush (ha un metodo' strict_sync() 'che dovrebbe chiamare' flush() 'su ogni dispositivo nella pipeline, che anch'io ho provato, inutilmente). – cce
Grazie per questo - stavo incontrando lo stesso problema. Nessuno svuotamento disponibile e strict_sync non ha avuto alcun effetto. – erikreed