Распаковка gzip-файла в память с использованием libarchive - PullRequest
0 голосов
/ 21 января 2019

Я пытаюсь программно распаковать gzip-файл в память и имитировать команду gzip -d file.gz, используя libarchive project . Файл фактически взят из ответа http со следующим заголовком Accept-Encoding: gzip, deflate

Вот моя попытка прочитать файл. Я не ожидаю, что это не сработает, поскольку в файле gzipped нет записей (он сжат как поток), а archive_read_next_header пытается прочитать следующий файл из arcihve.

Есть ли альтернатива этой функции, которая извлекает все данные из сжатого файла.

archive_read_support_format_raw(archive); 
archive_read_support_filter_all(archive);
archive_read_support_compression_all(archive)

archive_read_open_memory(archive, file_data, file_size);
struct archive_entry *entry;
la_ssize_t total, size;
char *buf;    
int status = archive_read_next_header(archive, &entry);

Возможно, кто-то может опубликовать минимальный пример кода, который решит эту проблему? Кроме того, есть ли возможность узнать, есть ли в архиве gzip записи или нет?

Ответы [ 2 ]

0 голосов
/ 15 марта 2019

Есть два способа сделать это, используя zlib:

  1. Использование встроенного API GzFile: Coliru Link - Подробнее об этом здесь
int inf(FILE* fp) {
    auto gzf = ::gzdopen(fileno(fp), "r");
    assert(::gztell(gzf) == 0);
    std::cout << "pos: " << ::gztell(gzf) << std::endl;
    ::gzseek(gzf, 18L, SEEK_SET);
    char buf[768] = {0};
    ::gzread(gzf, buf, sizeof(buf)); // use a custom size as needed
    std::cout << buf << std::endl; // Print file contents from 18th char onward
    ::gzclose(gzf);
    return 0;
}
  1. Нативный inflate API: Coliru Link . Подробнее об этом в руководстве по ссылке выше и здесь . Мой код почти полностью дублирует предоставленную ссылку и довольно длинный, поэтому я не буду перепечатывать.
0 голосов
/ 21 января 2019

Одной из возможных альтернатив является использование библиотеки boost::iostreams, которая поставляется со встроенным фильтром gzip и позволяет выполнять именно то, что вам нужно - потоковую распаковку из файла gzip в памяти. Вот ссылка на gzip фильтр и фрагмент из того же:

ifstream file("hello.gz", ios_base::in | ios_base::binary);
filtering_streambuf<input> in;
in.push(gzip_decompressor());
in.push(file);
boost::iostreams::copy(in, cout);

Редактировать: На самом деле гораздо лучший фрагмент доступен здесь https://stackoverflow.com/a/16693807/3656081

...