【问题标题】:How to determine compressed size from zlib for gzipped data?如何从 zlib 确定压缩数据的压缩大小?
【发布时间】:2011-01-07 09:29:49
【问题描述】:

我正在使用 zlib 执行 gzip 压缩。 zlib 将数据压缩后直接写入打开的 TCP 套接字。

/* socket_fd is a file descriptor for an open TCP socket */
gzFile gzf = gzdopen(socket_fd, "wb");
int uncompressed_bytes_consumed = gzwrite(gzf, buffer, 1024);

(当然所有错误处理都被删除了)

问题是:如何确定向套接字写入了多少字节? zlib 中的所有 gz* 函数都处理未压缩域中的字节数/偏移量,并且 tell (seek) 不适用于套接字。

zlib.h 标头显示“该库也可以选择性地在内存中读取和写入 gzip 流。”写入缓冲区会起作用(然后我可以随后将缓冲区写入套接字),但我看不到如何使用接口来做到这一点。

【问题讨论】:

    标签: sockets gzip zlib


    【解决方案1】:

    您可以通过deflate* 系列调用来完成此操作。我不会向您展示所有内容,但是这个示例程序(我在目录中将其命名为“test.c”)应该可以帮助您入门:

    #include <zlib.h>
    #include <stdlib.h>
    #include <stdio.h>
    
    char InputBufferA[4096];
    char OutputBufferA[4096];
    
    int main(int argc, char *argv[])
    {
        z_stream Stream;
        int InputSize;
        FILE *FileP;
    
        Stream.zalloc = malloc;
        Stream.zfree = free;
        /* initialize compression */
        deflateInit(&Stream, 3);
        FileP = fopen("test.c", "rb");
        InputSize = fread((void *) InputBufferA, 1, sizeof(InputBufferA), FileP);
        fclose(FileP);
        Stream.next_in = InputBufferA;
        Stream.avail_in = InputSize;
        Stream.next_out = OutputBufferA;
        Stream.avail_out = sizeof(OutputBufferA);
        deflate(&Stream, Z_SYNC_FLUSH);
        /* OutputBufferA is now filled in with the compressed data. */
        printf("%d bytes input compressed to %d bytes\n", Stream.total_in, Stream.total_out);
        exit(0);
    }
    

    zlib.h 查阅deflate 文档。

    【讨论】:

    • 不确定我是否遗漏了什么,但这似乎不会生成 gzip 格式的数据。
    【解决方案2】:

    zlib 实际上可以将 gzip 格式的数据写入内存中的缓冲区。

    zlib faq 条目遵循 zlib.h 中的 cmets。在头文件中,deflateInit2() 的注释提到您应该(任意?)将 16 添加到第 4 个参数(windowBits),以使库使用 gzip 格式(而不是默认的“zlib " 格式)。

    此代码正确设置 zlib 状态以将 gzip 编码到缓冲区:

    #include <zlib.h>
    z_stream stream;
    stream.zalloc = Z_NULL;
    stream.zfree = Z_NULL;
    stream.opaque = Z_NULL;
    int level = Z_DEFAULT_COMPRESSION;
    int method = Z_DEFLATED;  /* mandatory */
    int windowBits = 15 + 16; /* 15 is default as if deflateInit */
                              /* were used, add 16 to enable gzip format */
    int memLevel = 8;         /* default */
    int strategy = Z_DEFAULT_STRATEGY;
    if(deflateInit2(&stream, level, method, windowBits, memLevel, strategy) != Z_OK)
    {
        fprintf(stderr, "deflateInit failed\n");
        exit(EXIT_FAILURE);
    }
    
    /* now use the deflate function as usual to gzip compress */
    /* from one buffer to another. */
    

    我确认此过程产生与 gzopen/gzwrite/gzclose 接口完全相同的二进制输出。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-13
      • 1970-01-01
      相关资源
      最近更新 更多