2011-06-21 8 views
15

Logré integrar las API de impulso de Iostream para leer archivos comprimidos. Me seguido la documentación en la página impulso y tienen el siguiente código tan lejos:¿Cómo puedo leer línea por línea usando la interfaz Boost IOStreams para archivos Gzip?

std::stringstream outStr; 
ifstream file("file.gz", ios_base::in | ios_base::binary); 
try { 
    boost::iostreams::filtering_istreambuf in; 
    in.push(boost::iostreams::gzip_decompressor()); 
    in.push(file); 
    boost::iostreams::copy(in, outStr); 
} 
catch(const boost::iostreams::gzip_error& exception) { 
    int error = exception.error(); 
    if (error == boost::iostreams::gzip::zlib_error) { 
     //check for all error code  
    } 
} 

El código funciona bien (así que por favor no hagáis caso de erratas y errores anteriores. :)).

  1. Parece que el código anterior leerá el archivo completo y almacenarlo en la memoria durante la creación de la filtering_istreambuf. ¿Es eso cierto, desde mi investigación, me parece así? Si el archivo se lee en la memoria, este código puede ser un problema para archivos grandes (que es lo que estoy tratando).
  2. Mi código actual lee el gzip usando la API de gzgets de zlib línea por línea. ¿Hay alguna manera de hacer lectura línea por línea usando API de impulso?

Respuesta

20

1) Sí, el código anterior será copy() el archivo completo en el almacenamiento intermedio de cadenas outStr. De acuerdo con la description of copy

La copia plantilla de función lee datos de un determinado modelo de fuente y lo escribe en un determinado modelo de fregadero hasta que se llega al final de la secuencia.

2) cambio de filtering_istreambuf a filtering_istream y std :: getline() funcionará:.

#include <iostream> 
#include <fstream> 
#include <boost/iostreams/filtering_stream.hpp> 
#include <boost/iostreams/filter/gzip.hpp> 
int main() 
{ 
    std::ifstream file("file.gz", std::ios_base::in | std::ios_base::binary); 
    try { 
     boost::iostreams::filtering_istream in; 
     in.push(boost::iostreams::gzip_decompressor()); 
     in.push(file); 
     for(std::string str; std::getline(in, str);) 
     { 
      std::cout << "Processed line " << str << '\n'; 
     } 
    } 
    catch(const boost::iostreams::gzip_error& e) { 
     std::cout << e.what() << '\n'; 
    } 
} 

(puede std::cout << file.tellg() << '\n'; dentro de ese bucle si quieres una prueba Aumentará en trozos considerables, pero no será igual a la longitud del archivo desde el inicio)

+0

gracias. Déjame probar esto. Tengo la esperanza de almacenar < in> como miembro de la clase. y tener una función miembro en la clase llamada getline. getline debería poder devolver la línea desde la posición actual del puntero de archivo. – cppcoder

Cuestiones relacionadas