Распаковка в памяти с помощью zlib - PullRequest
3 голосов
/ 04 февраля 2011

Могу ли я прочитать сжатый файл zlib в памяти без фактического извлечения его на диск?Было бы неплохо, если бы вы могли предоставить фрагмент.

Ответы [ 3 ]

17 голосов
/ 29 декабря 2011

Вот процедура 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.

0 голосов
/ 21 февраля 2019

Решение, предоставленное Раджем Адвани, не работает для многопоточного буфера 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

0 голосов
/ 05 февраля 2011

Да, вы можете;zlib обычно используется во встроенных системах для распаковки образа приложения из ПЗУ в ОЗУ - операция полностью из памяти в память.

В документации zlib описаны необходимые вызовы.

...