【问题标题】:Decompressing gzip file to memory using libarchive使用 libarchive 将 gzip 文件解压缩到内存
【发布时间】:2019-01-21 08:18:43
【问题描述】:

我正在尝试以编程方式将 gzip 文件解压缩到内存中,并使用 libarchive project 模拟命令 gzip -d file.gz。 该文件实际上取自http响应,带有以下标头Accept-Encoding: gzip, deflate

这是我读取文件的尝试。我不希望它不起作用,因为 gzip 压缩的文件没有条目(它被压缩为流)并且archive_read_next_header 尝试从存档中读取下一个文件。

这个函数有什么替代方法可以从压缩文件中提取整个数据。

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 存档文件是否有条目?

【问题讨论】:

  • gzip 不是 归档 格式。您应该寻找一个纯 gzip 或压缩库,libarchive 期望(顾名思义)一个存档。
  • @tkausl,感谢您清除此问题。也许您详细说明了 gzip 和另一种支持归档的压缩算法之间的区别?此外,您能否推荐支持 gzip 解压缩的最小、临时和无错误库(我已经检查过 boost,但我希望避免对 boost 的整个逻辑进行大规模部署)
  • 要解压文件,ala gzip -d file.gz ,使用 libz 做你想做的事。
  • Perhaps you elaborate about the difference between gzip and another compression algorithm that support archiving? 例如哪个?如果你想到tar.gz,它实际上是一个 tar 存档,它对压缩一无所知,用 gzip 压缩,它对存档一无所知。
  • 是的,.tar.gz 是一个 gzip 压缩的 .tar 存档,但是您可以 gzip 任何东西,因此 .gz 文件不一定也是一个存档。

标签: c++ c gzip deflate libarchive


【解决方案1】:

一种可能的替代方法是使用boost::iostreams 库,它带有一个内置的 gzip 过滤器,并允许您想要的 - 从内存中的 gzip 文件流式解压缩。这是对gzip filter 的引用,以及来自同一地址的sn-p:

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);

编辑:实际上这里有一个更好的 sn-p https://stackoverflow.com/a/16693807/3656081

【讨论】:

  • 嘿,感谢您的回答,我只是想知道您是否也可以向我指出基于 zlib 的实现。出于许可和部署的原因,我更愿意避免使用 boost。
【解决方案2】:

有两种方法可以使用zlib

  1. 使用内置 GzFile API:Coliru Link - 阅读更多关于此here
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。在上面的手动链接和here 中了解更多信息。我的代码几乎完全是提供的链接的副本,而且很长,所以我不会重新发布。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-02-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-01
    相关资源
    最近更新 更多