2012-10-22 3 views
2

J'ai une chaîne (d'une certaine longueur fixe), que j'ai besoin de compresser et de comparer ensuite les longueurs compressées (comme un proxy pour la redondance dans les données ou comme une approximation de la complexité de Kolmogorov). Actuellement, j'utilise boost :: iostreams pour la compression, ce qui semble bien fonctionner. Cependant, je ne sais pas comment obtenir la taille des données compressées. Quelqu'un peut-il aider, s'il vous plaît?longueur compressée d'une chaîne par boost :: iostreams

L'extrait de code est

#include <boost/iostreams/filtering_streambuf.hpp> 
#include <boost/iostreams/filtering_stream.hpp> 
#include <boost/iostreams/copy.hpp> 
#include <boost/iostreams/filter/gzip.hpp> 
#include <boost/iostreams/device/file_descriptor.hpp> 
#include <boost/filesystem.hpp> 
#include <string> 
#include <sstream> 

namespace io = boost::iostreams; 

int main() { 

    std::string memblock; 

    std::cout << "Input the string to be compressed:"; 
    std::cin >> memblock; 

    std::cout << memblock << std::endl; 

    io::filtering_ostream out; 
    out.push(io::gzip_compressor()); 
    out.push(io::file_descriptor_sink("test.gz")); 
    out.write (memblock.c_str(), memblock.size()); 

    std::cout << out.size() << std::endl; 

    return 0; 

} 
+1

Pouvez-vous écrire les données à un objet semblable à stringstream? Si c'est le cas, il est trivial d'obtenir le résultat sous forme de chaîne et d'obtenir sa longueur. –

Répondre

4

Vous pouvez essayer d'ajouter boost::iostreams::counter vous enchaînez entre le compresseur et un évier puis l'appeler est characters() membre pour obtenir le nombre d'octets qui sont passés par elle.

Cela fonctionne pour moi:

#include <boost/iostreams/filter/counter.hpp> 

...

io::filtering_ostream out; 
out.push(io::counter()); 
out.push(io::gzip_compressor()); 
out.push(io::counter()); 
out.push(io::file_descriptor_sink("test.gz")); 
out.write (memblock.c_str(), memblock.size()); 
io::close(out); // Needed for flushing the data from compressor 

std::cout << "Wrote " << out.component<io::counter>(0)->characters() << " bytes to compressor, " 
    << "got " << out.component<io::counter>(2)->characters() << " bytes out of it." << std::endl; 
+0

Merci beaucoup! Ça marche bien :) –

1

Je compris une autre (et un peu plus lisse) façon d'atteindre la longueur comprimée d'une chaîne. Je pensais partager ici, mais au fond, il est tout simplement passer la chaîne non compressée à un tampon filtré et copie de la sortie en une chaîne:

template<typename T> 
inline std::string compressIt(std::vector<T> s){ 

    std::stringstream uncompressed, compressed; 
    for (typename std::vector<T>::iterator it = s.begin(); 
     it != s.end(); it++) 
     uncompressed << *it; 

    io::filtering_streambuf<io::input> o; 
    o.push(io::gzip_compressor()); 
    o.push(uncompressed); 
    io::copy(o, compressed); 

    return compressed.str(); 
} 

plus tard, on peut facilement obtenir la taille de la chaîne compressée comme

compressIt(uncompressedString).size() 

Je pense que c'est mieux car cela ne m'oblige pas à créer un fichier de sortie comme précédemment.

acclamations, Nikhil

0

une autre façon serait

stream<array_source> input_stream(input_data,input_data_ize); 
stream<array_sink> compressed_stream(compressed_data,alloc_compressed_size); 
filtering_istreambuf out; 
out.push(gzip_compressor()); 
out.push(input_stream); 
int compressed_size = copy(out,compressed_stream); 
cout << "size of compressed_stream" << compressed_size << endl; 
Questions connexes