2009-11-18 19 views
25

używam biblioteki serializacji doładowania, co jest rzeczywiście bardzo ładny, i pozwala mi wykonywać proste owijarki, aby zapisać swoje serializacji obiektów do strun, tak jak poniżej:Jak podłączyć Wzmocnienie serializacji i iostreams do serializacji i gzip obiektu do napisu?

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

Chodzi o to, po prostu okazało się, że muszę również skompresować moje zserializowane dane, więc szukam tego z filtrami w boost :: iostreams. Pomyślałem, jak to zrobić z powodzeniem z plikami:

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

Ale nie mogę dowiedzieć się, jak poprawnie zapisać skompresowany ciąg. Problem polega na tym, że nie przepłukiwam łańcucha filtrów, ale próbowałem robić popping i synchronizować i nic nie działa. Oto mój złamany kod:

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

W rezultacie niektóre dane utknie w buforze strumienia gdzieś, a ja zawsze skończyć z aa kilku kompletnych bloków (16K lub 32K) skompresowanych danych, gdy wiem, że powinien on być 43K lub tak, biorąc pod uwagę (poprawne) dane wyjściowe otrzymuję z wykorzystaniem mojej metody saveGZFile. Wygląda na to, że podpięcie się zamyka i spłukuje, ale podpięcie ostringstream nie.

Każda pomoc? (To jest moje pierwsze pytanie stackoverflow - pomóż mi, chłopaki, jesteś moją jedyną nadzieją!)

Odpowiedz

19

Wracając do tego pytania, zdałem sobie sprawę, że muszę to naprawić w zeszłym roku (ponieważ używam teraz saveGZString). Kopanie, aby zobaczyć, jak to naprawiłem, było dość głupie/proste:

Po prostu pozwól, aby cały łańcuch przestał działać i działa! Schludny! Oto mój ładowacz dla kompletności:

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

Możesz uniknąć sztuczki z ograniczeniem zasięgu za pomocą wywołania flush(). f.flush() –

+1

w niepracującym kodzie w moim pytaniu, komentarz mówi "' oss.flush() ?? '" ponieważ wywołanie 'flush()' na 'ostringstream' nie działało. sztuczka z ograniczeniem zasięgu jest jedyną rzeczą, która zadziałała dla mnie. chyba że masz na myśli, że powinienem wypróżnić 'f', który nie ma metody flush (ma metodę' strict_sync() ', która powinna wywoływać' flush() 'na każdym urządzeniu w potoku, które również próbowałem, bez skutku). – cce

+0

Dzięki za to - natknąłem się na ten sam problem. Brak opcji spłukiwania, a strict_sync nie ma żadnego efektu. – erikreed

1

Nie uruchomić kod siebie, ale mój najlepszy przypuszczenie jest użycie out.strict_sync() która odnosi się do każdego filterflush()/device w przygotowaniu. Nie mogę jednak stwierdzić, czy gzip_compressor jest flushable. Jeśli tak nie jest, wówczas strict_sync() zwróci wartość false, a sync() będzie bardziej odpowiednie.

+0

+1 To pachnie jak kolor! – fmuecke

+0

Wewnętrznie, jest w kolorze. Ale jest on nakładany równo na każdy filtr/urządzenie w łańcuchu. – rcollyer

+1

jak pamiętam (dawno temu) Próbowałem 'strict_sync()' i to nie działało, jak również inne rzeczy w sfrustrowanej linii '// XXX ??' w moim pytaniu ... może to działa w najnowszym Boostu, kto wie. – cce