Pergunta

Tenho usado a biblioteca de serialização Boost, que é realmente muito boa e me permite criar wrappers simples para salvar meus objetos serializáveis ​​em strings, assim:

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;
}

O problema é que acabei de descobrir a necessidade de compactar meus dados serializados também, então estou pensando em fazer isso com os filtros em boost::iostreams.Eu descobri como fazer isso com sucesso com arquivos:

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;
}

Mas não consigo descobrir como salvar corretamente em uma string compactada.O problema é que não estou liberando a cadeia de filtros, mas tentei abrir e sincronizar e nada parece funcionar.Aqui está meu código quebrado:

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, alguns dados ficam presos no buffer de fluxo em algum lugar, e sempre acabo com alguns blocos completos (16K ou 32K) de dados compactados quando sei que deveriam ser 43K ou mais, dada a saída (válida) que obtenho usando meu método saveGZFile.Aparentemente, conectar o ofstream fecha e libera corretamente, mas conectar o ostringstream não.

Qualquer ajuda?(Esta é minha primeira pergunta sobre stackoverflow - ajudem-me, pessoal, vocês são minha única esperança!)

Foi útil?

Solução

Voltando a esta questão, percebi que devo tê-la corrigido em algum momento do ano passado (já que estou usando saveGZString agora).Procurando para ver como consertei, foi bem bobo/simples:

namespace bar = boost::archive;
namespace bio = boost::iostreams;

template <typename T> inline std::string saveGZString(const T & o) {
        std::ostringstream oss;
        { 
                bio::filtering_stream<bio::output> f;
                f.push(bio::gzip_compressor());
                f.push(oss);
                bar::binary_oarchive oa(f);
                oa << o;
        } // gzip_compressor flushes when f goes out of scope
        return oss.str();
}

Basta deixar toda a cadeia sair do escopo e funciona!Organizado!Aqui está meu carregador para completar:

template <typename T> inline void loadGZString(T & o, const std::string& s) {
        std::istringstream iss(s);
        bio::filtering_stream<bio::input> f;
        f.push(bio::gzip_decompressor());
        f.push(iss);
        bar::binary_iarchive ia(f);
        ia >> o;
}

Outras dicas

Eu não executei o código sozinho, mas meu melhor palpite é usar out.strict_sync() que se aplica flush() a cada filter/device no pipeline.Eu não consigo dizer, porém, se gzip_compressor é flushable.Se não for, então strict_sync() retornará falso e sync() seria mais apropriado.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top