2011-06-21 9 views
15

Udało mi się zintegrować funkcje wspomagające Iostream API do odczytu skompresowanych plików. Poszedłem za dokumentację w stronę doładowania i mieć następujący kod narazie:Jak mogę czytać linia po linii za pomocą interfejsu Boost IOStreams dla plików 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  
    } 
} 

Kod działa poprawnie (więc proszę ignorować wszelkie literówki i błędy wyżej :).).

  1. Wygląda na to, że powyższy kod przeczyta cały plik i zapisze go w pamięci podczas tworzenia filtrującego filtra. Czy to prawda, z mojego śledztwa tak mi się wydaje? Jeśli plik jest wczytany do pamięci, ten kod może być problemem w przypadku dużych plików (z czym mam do czynienia).
  2. Mój aktualny kod czyta gzipped za pomocą interfejsu API gzgets z linii zlib po linii. Czy istnieje sposób na czytanie linii po linii za pomocą funkcji boost API?

Odpowiedz

20

1) Tak, powyższy kod będzie copy() cały plik w buforze ciągowym outStr. Według description of copy

Funkcja szablonu kopia odczytuje dane z danego modelu Źródło i zapisuje go do danego modelu Sink do końca strumienia jest osiągnięty.

2) przełącznik od filtering_istreambuf do filtering_istream i std :: getline() będzie działać.

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

(może std::cout << file.tellg() << '\n'; wewnątrz tej pętli ty, jeśli chcesz dowód Zwiększy to w znacznych fragmentów, ale nie będzie równa długości pliku od początku)

+0

dzięki. Pozwól mi to wypróbować. Mam nadzieję, że jako członek klasy będę przechowywać < in>. i mają funkcję member w klasie o nazwie getline. getline powinien mieć możliwość powrotu do linii od aktualnej pozycji wskaźnika pliku. – cppcoder

Powiązane problemy