使用 zlib 进行内存解压

发布于 2024-10-15 16:47:39 字数 55 浏览 2 评论 0原文

我可以读取内存中的 zlib 压缩文件而不将其实际解压到磁盘吗?如果您能提供一个片段那就太好了。

Can I read a zlib compressed file in memory without actually extracting it to disk? It would be nice if you could provide a snippet.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

飘逸的'云 2024-10-22 16:47:39

这是一个 zLib inflate 例程,它获取内存中的缓冲区并将其解压缩到提供的输出缓冲区中。这是一个“一次性”函数,因为它尝试一次性填充整个输入缓冲区,并假设您已经为其提供了足够的空间来容纳所有内容。还可以编写一个多镜头函数,根据需要动态增长目标缓冲区。

int inflate(const void *src, int srcLen, void *dst, int dstLen) {
    z_stream strm  = {0};
    strm.total_in  = strm.avail_in  = srcLen;
    strm.total_out = strm.avail_out = dstLen;
    strm.next_in   = (Bytef *) src;
    strm.next_out  = (Bytef *) dst;

    strm.zalloc = Z_NULL;
    strm.zfree  = Z_NULL;
    strm.opaque = Z_NULL;

    int err = -1;
    int ret = -1;

    err = inflateInit2(&strm, (15 + 32)); //15 window bits, and the +32 tells zlib to to detect if using gzip or zlib
    if (err == Z_OK) {
        err = inflate(&strm, Z_FINISH);
        if (err == Z_STREAM_END) {
            ret = strm.total_out;
        }
        else {
             inflateEnd(&strm);
             return err;
        }
    }
    else {
        inflateEnd(&strm);
        return err;
    }

    inflateEnd(&strm);
    return ret;
}

说明:

src:包含压缩(gzip或zlib)数据的源缓冲区
srcLen:源缓冲区的长度
dst:目标缓冲区,输出将写入其中
dstLen:目标缓冲区的长度

返回值:

Z_BUF_ERROR:如果dstLen不够大,无法容纳膨胀的数据
Z_MEM_ERROR:如果没有足够的内存来执行解压
Z_DATA_ERROR:如果输入数据已损坏

否则,返回值是写入 dst 的字节数。

Here's a zLib inflate routine that takes a buffer in memory and decompresses into the provided output buffer. This is a 'one-shot' function, in that it attempts to inflate the entire input buffer all at once, and assumes you've given it enough space to fit it all. It is also possible to write a multi-shot function that dynamically grows the destination buffer as needed.

int inflate(const void *src, int srcLen, void *dst, int dstLen) {
    z_stream strm  = {0};
    strm.total_in  = strm.avail_in  = srcLen;
    strm.total_out = strm.avail_out = dstLen;
    strm.next_in   = (Bytef *) src;
    strm.next_out  = (Bytef *) dst;

    strm.zalloc = Z_NULL;
    strm.zfree  = Z_NULL;
    strm.opaque = Z_NULL;

    int err = -1;
    int ret = -1;

    err = inflateInit2(&strm, (15 + 32)); //15 window bits, and the +32 tells zlib to to detect if using gzip or zlib
    if (err == Z_OK) {
        err = inflate(&strm, Z_FINISH);
        if (err == Z_STREAM_END) {
            ret = strm.total_out;
        }
        else {
             inflateEnd(&strm);
             return err;
        }
    }
    else {
        inflateEnd(&strm);
        return err;
    }

    inflateEnd(&strm);
    return ret;
}

Explanation:

src: the source buffer containing the compressed (gzip or zlib) data
srcLen: the length of the source buffer
dst: the destination buffer, into which the output will be written
dstLen: the length of the destination buffer

Return values:

Z_BUF_ERROR: if dstLen is not large enough to fit the inflated data
Z_MEM_ERROR: if there's insufficient memory to perform the decompression
Z_DATA_ERROR: if the input data was corrupt

Otherwise, the return value is the number of bytes written to dst.

对不⑦ 2024-10-22 16:47:39

Raj Advani 提供的解决方案不适用于多流 zlib 缓冲区。 gzip数据的解决方案:

void decompress(Bytef *src, int src_len, Bytef *dst, int dst_len)
{
    z_stream strm  = {0};
    strm.zalloc = Z_NULL;
    strm.zfree  = Z_NULL;
    strm.opaque = Z_NULL;

    while (src_len > 0)
    {
        strm.total_in  = strm.avail_in  = src_len;
        strm.total_out = strm.avail_out = dst_len;
    strm.next_in   = src;
        strm.next_out  = (Bytef *) dst;
        assert(inflateInit2(&strm, (MAX_WBITS + 16)) == Z_OK);
        decompress_block(&strm, dst);
    unsigned int processed = src_len - strm.avail_in;
        src_len -= processed;
        src += processed;
    }
}

int decompress_block(z_stream *strm, void *dst)
{
    int ret;
    do
    {
        ret = inflate(strm, Z_NO_FLUSH);
        assert(ret != Z_STREAM_ERROR && ret != Z_NEED_DICT && ret != Z_MEM_ERROR && ret != Z_DATA_ERROR);
        assert(strm->avail_out > 0);
    }
    while (ret != Z_STREAM_END);
    inflateEnd(strm);
    assert(write(1, dst, strm->total_out) == strm->total_out);
    return 0;
}

https://github.com/uvoteam/gunzip_mmap

Solution provided by Raj Advani does not work for multistream zlib buffer. Solution for gzip data:

void decompress(Bytef *src, int src_len, Bytef *dst, int dst_len)
{
    z_stream strm  = {0};
    strm.zalloc = Z_NULL;
    strm.zfree  = Z_NULL;
    strm.opaque = Z_NULL;

    while (src_len > 0)
    {
        strm.total_in  = strm.avail_in  = src_len;
        strm.total_out = strm.avail_out = dst_len;
    strm.next_in   = src;
        strm.next_out  = (Bytef *) dst;
        assert(inflateInit2(&strm, (MAX_WBITS + 16)) == Z_OK);
        decompress_block(&strm, dst);
    unsigned int processed = src_len - strm.avail_in;
        src_len -= processed;
        src += processed;
    }
}

int decompress_block(z_stream *strm, void *dst)
{
    int ret;
    do
    {
        ret = inflate(strm, Z_NO_FLUSH);
        assert(ret != Z_STREAM_ERROR && ret != Z_NEED_DICT && ret != Z_MEM_ERROR && ret != Z_DATA_ERROR);
        assert(strm->avail_out > 0);
    }
    while (ret != Z_STREAM_END);
    inflateEnd(strm);
    assert(write(1, dst, strm->total_out) == strm->total_out);
    return 0;
}

https://github.com/uvoteam/gunzip_mmap

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文