He estado usando la biblioteca Boost serialización, que en realidad es bastante agradable, y me permite hacer simples envoltorios para guardar mis objetos serializables a las cadenas, así:Cómo conectar la serialización de Boost y iostreams para serializar y convertir gzip un objeto en una cadena?
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;
}
Lo que pasa es que acabo de encontrar la necesito comprimir mis datos serializados también, así que estoy buscando hacerlo con los filtros en boost :: iostreams. Me di cuenta de cómo hacerlo con éxito con los archivos:
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;
}
Pero no puede encontrar la manera de guardar correctamente a una cadena comprimida. El problema es que no estoy descargando la cadena de filtros, pero he intentado hacer estallar y sincronizar y nada parece funcionar. Aquí está mi código roto:
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();
}
Como resultado, algunos datos se queda atascado en el búfer de la secuencia en alguna parte, y siempre termino con aa pocos bloques completos (16K o 32K) de datos comprimidos cuando sé que debería ser 43K más o menos dado el resultado (válido) que obtengo de usar mi método saveGZFile. Aparentemente, conectar el flujo de corriente se cierra y se vacía correctamente, pero conectar el ostringstream no.
¿Algún ayuda? (Esta es mi primera pregunta StackOverflow - me ayude, chicos, eres mi única esperanza!)
Puede evitar el truco de limitación del alcance con una llamada a flush(). f.flush() –
en el código que no funciona en mi pregunta, el comentario dice "' oss.flush() ?? '" porque la llamada 'flush()' en 'ostringstream' no funcionaba. el truco de limitación de alcance es lo único que funcionó para mí. a menos que quieras decir que debería tirar 'f', que no tiene un método de enjuague (tiene un método' strict_sync() 'que se supone que llama a' flush() 'en cada dispositivo en la tubería, que también intenté, en vano). – cce
Gracias por esto, me encontré con el mismo problema. No hay descarga disponible y strict_sync no tuvo ningún efecto. – erikreed