在C中放气和膨胀(zlib.h)

时间:2011-09-24 16:27:48

标签: c compression zlib deflate

我正在尝试实现zlib.h deflate和inflate函数来压缩和解压缩char数组(而不是文件)。

我想知道以下语法是否正确?我错过了什么或者错误地定义了什么吗?

char a[50] = "Hello World!";
char b[50];
char c[50];

// deflate
// zlib struct
z_stream defstream;
defstream.zalloc = Z_NULL;
defstream.zfree = Z_NULL;
defstream.opaque = Z_NULL;
defstream.avail_in = (uInt)sizeof(a); // size of input
defstream.next_in = (Bytef *)a; // input char array
defstream.avail_out = (uInt)sizeof(b); // size of output
defstream.next_out = (Bytef *)b; // output char array

deflateInit(&defstream, Z_DEFAULT_COMPRESSION);
deflate(&defstream, Z_FINISH);
deflateEnd(&defstream);

printf("Deflate:\n%lu\n%s\n", strlen(b), b);

// inflate
// zlib struct
z_stream infstream;
infstream.zalloc = Z_NULL;
infstream.zfree = Z_NULL;
infstream.opaque = Z_NULL;
infstream.avail_in = (uInt)sizeof(b); // size of input
infstream.next_in = (Bytef *)b; // input char array
infstream.avail_out = (uInt)sizeof(c); // size of output
infstream.next_out = (Bytef *)c; // output char array

inflateInit(&infstream);
inflate(&infstream, Z_NO_FLUSH);
inflateEnd(&infstream);

printf("Inflate:\n%lu\n%s\n", strlen(c), c);

3 个答案:

答案 0 :(得分:25)

zlib已经有了一个简单的膨胀/收缩功能。

char a[50] = "Hello, world!";
char b[50];
char c[50];

uLong ucompSize = strlen(a)+1; // "Hello, world!" + NULL delimiter.
uLong compSize = compressBound(ucompSize);

// Deflate
compress((Bytef *)b, &compSize, (Bytef *)a, ucompSize);

// Inflate
uncompress((Bytef *)c, &ucompSize, (Bytef *)b, compSize);

如有疑问,请查看zlib manual。 我的代码很糟糕,抱歉= /

答案 1 :(得分:7)

你不能像这样打印缩小的输出。它不是空终止。你也不能纠结它。

由于您的输入是一个字符串,但您可能只希望传递包含空终止符的字符串内容。所以将avail_in设置为strlen(a)+ 1。

在调用deflate后,您需要检查next_out和avail_out字段,以查看有多少数据写入输出缓冲区。

请参阅deflate调用下的文档here

这是您修改后的代码。请注意,如果您正在压缩不是字符串的内容,则需要更改此字符串以及字符串,您可以在没有终止零的情况下进行压缩,并在解压缩后将其添加回来。

char a[50] = "Hello World!";
char b[50];
char c[50];

// deflate
// zlib struct
z_stream defstream;
defstream.zalloc = Z_NULL;
defstream.zfree = Z_NULL;
defstream.opaque = Z_NULL;
defstream.avail_in = (uInt)strlen(a)+1; // size of input, string + terminator
defstream.next_in = (Bytef *)a; // input char array
defstream.avail_out = (uInt)sizeof(b); // size of output
defstream.next_out = (Bytef *)b; // output char array

deflateInit(&defstream, Z_DEFAULT_COMPRESSION);
deflate(&defstream, Z_FINISH);
deflateEnd(&defstream);

// This is one way of getting the size of the output
printf("Deflated size is: %lu\n", (char*)defstream.next_out - b);

// inflate
// zlib struct
z_stream infstream;
infstream.zalloc = Z_NULL;
infstream.zfree = Z_NULL;
infstream.opaque = Z_NULL;
infstream.avail_in = (uInt)((char*)defstream.next_out - b); // size of input
infstream.next_in = (Bytef *)b; // input char array
infstream.avail_out = (uInt)sizeof(c); // size of output
infstream.next_out = (Bytef *)c; // output char array

inflateInit(&infstream);
inflate(&infstream, Z_NO_FLUSH);
inflateEnd(&infstream);

printf("Inflate:\n%lu\n%s\n", strlen(c), c);

答案 2 :(得分:2)

zpipe示例(http://zlib.net/zpipe.c)几乎涵盖了它,只需删除文件操作(带有前缀的函数),然后替换inout使用内存缓冲区,尽管根据您的使用情况,仅替换in或保持缓冲区可能就足够了。请注意,如果您计划使用未知大小的块,则需要调整 out 缓冲区的大小以解决任意大小的数据