如何从zlib确定压缩数据的压缩大小?

时间:2010-01-20 17:42:58

标签: sockets gzip zlib

我正在使用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流。”写入缓冲区会起作用(然后我可以随后将缓冲区写入套接字),但我看不到如何使用该接口。

2 个答案:

答案 0 :(得分:0)

您可以使用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);
}

查阅deflate中的zlib.h文档。

答案 1 :(得分:0)

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

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

此代码正确设置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接口完全相同的二进制输出。