Как я могу читать построчно, используя интерфейс Boost IOStreams для файлов Gzip?
Мне удалось интегрировать API повышения Iostream для чтения сжатых файлов. Я следовал за документацией на странице Boost и пока имею следующий код:
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. Это правда, из моего расследования это выглядит так для меня? Если файл читается в память, этот код может быть проблемой для больших файлов (с чем я имею дело).
- Мой текущий код читает g zipped с помощью API gzgets из zlib строка за строкой. Есть ли способ сделать построчное чтение, используя API-интерфейсы повышения?
1 ответ
Решение
1) Да, приведенный выше код copy()
весь файл в строковый буфер outStr
, По описанию копии
Функция шаблона copy считывает данные из заданной модели Source и записывает их в заданную модель Sink, пока не будет достигнут конец потока.
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';
внутри этого цикла, если вы хотите доказательства. Это увеличит размер кусков, но не будет равным длине файла с самого начала)