ускорение чтения файлов в формате gzip - PullRequest
2 голосов
/ 08 августа 2010

Я использую boost::iostreams::gzip_decompressor с boost::iostreams::filterimg_streambuf для чтения файлов gzip.

некоторые из моих файлов имеют то, что zcat называет trailing trash

% zcat somefile
data
data
data

gzip: somefile: decompression OK, trailing garbage ignored

Я хочу, чтобы boost gzip вел себя так же.

При попытке распаковать тот же файл с помощью boost, используя следующую функцию, я получаю исключение gzip_error (bad_header)

static int read_gzip(fs::path f, stringstream& s)
{
        ifstream file(f.string().c_str(), ios_base::in | ios_base::binary);
        io::filtering_streambuf<io::input> in;

        in.push(io::gzip_decompressor());
        in.push(file);

        try { 
            io::copy(in, s);
            return 1;
        }
        catch (io::gzip_error& e) {
            fprintf(stderr, "(read_gzip) io::copy exception %s %s (%d)\n", f.string().c_str(), e.what(), e.error());
        }

        return 0;
}

когда выдается исключение, stingstream остается пустым.

В качестве обходного пути я могу прочитать данные побайтно, используя что-то вроде этого:

static int read_gzip(fs::path f, string& s)
{
        ifstream file(f.string().c_str(), ios_base::in | ios_base::binary);
        io::filtering_streambuf<io::input> in;
        char buf[1];

        in.push(io::gzip_decompressor());
        in.push(file);

        try { 
            std::streamsize result;
            while ((result = io::read(in, buf, 1)) != -1) {
                s.append(buf, 1);
            }

            return 1;
        }
        catch (io::gzip_error& e) {
            fprintf(stderr, "(read_gzip) io::copy exception %s %s (%d)\n", f.string().c_str(), e.what(), e.error());
        }

        return 0;
} 

но это кажется довольно неэффективным.

Как правильно читать сжатые файлы с конечным мусором?

Спасибо.

1 Ответ

2 голосов
/ 09 августа 2010

Хорошо, наконец-то у меня получилось использовать zlib с другими window_bits, чтобы он мог распаковать gzip.

#include <zlib.h> # for MAX_WBITS

static int read_gzip(fs::path f, stringstream& s)
{
        ifstream file(f.string().c_str(), ios_base::in | ios_base::binary);
        io::filtering_streambuf<io::input> in;

        io::zlib_params p;
        p.window_bits = 16 + MAX_WBITS;

        in.push(io::zlib_decompressor(p));
        in.push(file);

        try { 
            io::copy(in, s);
            return 1;
        }
        catch (io::zlib_error & e) {
            fprintf(stderr, "(read_gzip) io::copy exception %s :: %s (%d)", f.string().c_str(), e.what(), e.error());
        }

     return 0;
}

распаковывает как обычные файлы gzip, так и файлы gzip с завершающим мусором без исключения.

...