本文介绍了确定 C 中 Z-lib 的压缩/未压缩缓冲区大小的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm using Zlib v1.2.7 to read a text file then compress it and write it to an output file. My problem is in the following example how can I determine the output buffer size based on input size? (in the example gz_length)I'm using this library for an STM32 Device. I added the unzip method and I have this problem as well for uncompressed data length.

#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;
}

推荐答案

如果你想在单个 deflate() 调用中进行压缩(顺便说一下,这不是必需的),zlib 提供了函数deflateBound() 正是为了这个目的.

If you want to compress in a single deflate() call (which is not necessary by the way), zlib provides the function deflateBound() for exactly this purpose.

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

There is no useful bound in the other direction. By not useful, I mean that the bound on the size of the decompressed output is over a thousand times the size of the compressed input.

这篇关于确定 C 中 Z-lib 的压缩/未压缩缓冲区大小的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-03 19:24