2012-02-28 4 views
6

estoy leyendo un archivo comprimido con gzip usando iostreams Boost: La siguiente funciona bien:¿Puede aumentar iostreams leer y comprimir archivos gzip sobre la marcha?

namespace io = boost::iostreams; 
    io::filtering_istream in; 
    in.push(boost::iostreams::basic_gzip_decompressor<>()); 
    in.push(io::file_source("test.gz")); 
    stringstream ss; 
    copy(in, ss); 

Sin embargo, yo no quiero recibir el golpe de memoria de lectura de todo un archivo comprimido con gzip en la memoria. Quiero poder leer el archivo de forma incremental.

Por ejemplo, si tengo una estructura de datos X que se inicializa desde istream,

X x; 
x.read(in); 

falla. Presumiblemente, esto se debe a que tendremos que volver a poner caracteres en la secuencia si estamos realizando transmisiones parciales. ¿Alguna idea de si impulsar iostreams apoya esto?

+0

¿Podría hacer una operación tal como llamar a 'getline()' 'luego comprimir()' a través de un bucle de trabajo para usted? – user99545

+0

@ user99545: No: porque X se crea a sí mismo a partir de datos binarios. – ATemp

+0

No veo por qué no. He usado boost iostreams para leer y escribir streams comprimidos zlib de esta manera. – Ferruccio

Respuesta

1

De acuerdo con iostream documentation el tipo boost::io::filtering_istream deriva de std::istream. Es decir, debería ser posible pasar esto a todas partes, se espera un std::istream&. Si tiene errores en el tiempo de ejecución porque necesita los caracteres unget() o putback(), debe echar un vistazo al parámetro pback_size que especifica cuántos caracteres son como máximo. No he visto en la documentación cuál es el valor predeterminado para este parámetro.

Si esto no resuelve su problema, ¿puede describir cuál es exactamente su problema? Desde el aspecto de debería funcionar.

1

Creo que necesita escribir su propio filtro. Por ejemplo, para leer un .tar.gz y salida de los archivos contenidos, escribí algo así como

//using namespace std; 
namespace io = boost::iostreams; 

struct tar_expander 
{ 
    tar_expander() : out(0), status(header) 
    { 
    } 
    ~tar_expander() 
    { 
     delete out; 
    } 

    /* qualify filter */ 
    typedef char char_type; 
    struct category : 
     io::input_filter_tag, 
     io::multichar_tag 
    { }; 

    template<typename Source> 
    void fetch_n(Source& src, std::streamsize n = block_size) 
    { 
      /* my utility */ 
      .... 
    } 

    // Read up to n filtered characters into the buffer s, 
    // returning the number of characters read or -1 for EOF. 
    // Use src to access the unfiltered character sequence 
    template<typename Source> 
    std::streamsize read(Source& src, char* s, std::streamsize n) 
    { 
     fetch_n(src); 
     const tar_header &h = cast_buf<tar_header>(); 
     int r; 

     if (status == header) 
     { 
      ... 
     } 
     std::ofstream *out; 
     size_t fsize, stored; 

     static const size_t block_size = 512; 
     std::vector<char> buf; 

     enum { header, store_file, archive_end } status; 
    } 
} 

Mi función read(Source &...) cuando se le llama recibe el texto descomprimido. Para utilizar el filtro:

ifstream file("/home/..../resample-1.8.1.tar.gz", ios_base::in | ios_base::binary); 
io::filtering_streambuf<io::input> in; 
in.push(tar_expander()); 
in.push(io::gzip_decompressor()); 
in.push(file); 
io::copy(in, cout); 
Cuestiones relacionadas