Как читать строку line- by-, используя интерфейс Boost IOStreams для файлов Gzip?

Мне удалось интегрировать повышающие API Iostream для чтения сжатых файлов. Я следил за документацией на странице повышения и имел следующий код so- far:

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

Код работает нормально (поэтому, пожалуйста, игнорируйте любые опечатки и ошибки выше:)).

  • Похоже, что приведенный выше код будет читать полный файл и хранить его в памяти при создании filtering_istreambuf. Это правда, из моего расследования это выглядит так для меня? Если файл считывается в память, этот код может быть проблемой для больших файлов (что я и имею в виду).
  • Мой текущий код читает gzipped с помощью gzgets API из zlib по строкам. Есть ли способ сделать чтение строк за строкой, используя расширенные API?

Ответ 1

1) Да, приведенный выше код будет copy() весь файл в буфере строк outStr. В соответствии с описанием копии

Копия шаблона функции считывает данные из данной модели источника и записывает их в данную модель раковины до тех пор, пока не будет достигнут конец потока.

2) переключитесь с filtering_istreambuf на filtering_istream, а std:: getline() будет работать:

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

(вы можете std::cout << file.tellg() << '\n'; внутри этого цикла, если вы хотите получить доказательство), он будет увеличиваться в значительных кусках, но он не будет равен длине файла с самого начала)