【问题标题】:Determine compressed/uncompressed buffer size for Z-lib in C确定 C 中 Z-lib 的压缩/未压缩缓冲区大小
【发布时间】:2018-11-09 16:39:53
【问题描述】:

我正在使用 Zlib v1.2.7 读取文本文件,然后将其压缩并将其写入输出文件。我的问题在以下示例中,如何根据输入大小确定输出缓冲区大小? (以gz_length为例) 我正在将此库用于 STM32 设备。我添加了 unzip 方法,并且对于未压缩的数据长度,我也遇到了这个问题。

#include "zlib.h"

int unzip(unsigned char *dst, unsigned long *dst_length, unsigned char *src, unsigned long src_length)
{
    z_stream stream;
    memset(&stream, 0, sizeof(stream));

    stream.next_in = src;
    stream.avail_in = src_length;

    stream.next_out = dst;
    stream.avail_out = *dst_length;

    int rv = inflateInit2(&stream, 15 + 16);
    if (Z_OK == rv) {
        rv = inflate(&stream, Z_NO_FLUSH);
        if (Z_STREAM_END == rv) {
            inflateEnd(&stream);
            rv = Z_OK;
        }
    }

    if (Z_OK == rv) {
        *dst_length = stream.total_out;
    } else {
        *dst_length = 0;
    }

    return rv;
}


int zip(unsigned char *dst, unsigned long *dst_length, unsigned char *src, unsigned long src_length)
{
    z_stream        stream;
    memset(&stream, 0, sizeof(stream));

    stream.next_in = src;
    stream.avail_in = src_length;

    stream.next_out = Z_NULL;
    stream.avail_out = 0;

    /* add 16 to MAX_WBITS to specify gzip format - it gets taken off again in defaultInit2 */
    int rv = deflateInit2(&stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 16 + MAX_WBITS, MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY);
    if (Z_OK == rv) {
        unsigned long dst_bound = deflateBound(&stream, stream.avail_in) + 12; /* 12 bytes for the gzip header */
        if (dst_bound > *dst_length) {
            rv = Z_MEM_ERROR;
        } else {
            stream.next_out   = dst;
            stream.avail_out = dst_bound;
        }
    }

    if (Z_OK == rv) {
        gz_header        header;
        memset(&header, 0, sizeof(header));
        rv = deflateSetHeader(&stream, &header);
    }

    if (Z_OK == rv) {
        rv = deflate(&stream, Z_FINISH);
        if (Z_STREAM_END == rv) {
            rv = deflateEnd(&stream);
        }
    }

    if (Z_OK == rv) {
        *dst_length = stream.total_out;
    } else {
        *dst_length = 0;
    }

    return rv;
}

int main()
{
    unsigned long read_size;
    unsigned char *buffer = NULL;
    unsigned char *gz_buffer = NULL;
    unsigned long input_size = 0;

    /* Open your_file in read-only mode */
    FILE *fp = fopen("/local/new.txt", "r");
    fseek(fp, 0, SEEK_END); /* Go to end of file */
    input_size = ftell(fp); /* How many bytes did we pass ? */
    printf("Filesize: %ld\n", input_size);
    /* Set position of stream to the beginning */
    rewind(fp);
    /* Allocate the buffer (no need to initialize it with calloc) */
    buffer = (unsigned char*) malloc((input_size + 1) * sizeof(*buffer)); /* input_size + 1 byte for the \0 */
    /* Read the file into the buffer */
    fread(buffer, input_size, 1, fp); /* Read 1 chunk of input_size bytes from fp into buffer */
    /* NULL-terminate the buffer */
    buffer[input_size] = '\0';
    /* Print it ! */
    printf("FileData: %s\n", buffer);
    fclose(fp);
    //PROBLEM HERE how to determine valid gz_length for output based on input_size
    unsigned long gz_length = input_size + 50;
    gz_buffer = (unsigned char*) malloc((gz_length) * sizeof(*gz_buffer));

    if (input_size > 0)
    {
        int rv = zip(gz_buffer, &gz_length, buffer, input_size);
        if (Z_OK == rv)
        {
            FILE *ofp = fopen("/local/out.gz", "w");
            if (ofp)
            {
                int bw = fwrite(gz_buffer, 1, gz_length, ofp);
                fclose(ofp);
            }
        }
        else
        {
            printf("%s:%d: %d%s", __FILE__, __LINE__, rv, newline);
        }
    }
    free(buffer);
    free(gz_buffer);
    return 0;
}

【问题讨论】:

    标签: c zlib


    【解决方案1】:

    如果您想在单个 deflate() 调用中进行压缩(顺便说一句,这不是必需的),zlib 提供了函数 deflateBound() 来实现此目的。

    在另一个方向上没有有用的界限。没有用,我的意思是解压缩输出大小的界限是压缩输入大小的一千多倍。

    【讨论】:

    • @谢谢。我发现this example 很有用,但是一次放气和多次放气有什么区别吗?
    • 结果没有区别。对于大型流,需要多少内存有很大差异。
    猜你喜欢
    • 2010-11-02
    • 1970-01-01
    • 2017-01-26
    • 1970-01-01
    • 2021-08-16
    • 2021-06-02
    • 2016-08-02
    • 2023-03-16
    • 2023-03-06
    相关资源
    最近更新 更多