11

我正在尝试实现 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);
4

3 回答 3

31

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 手册。我的代码很糟糕,对不起=/

于 2012-05-19T08:07:12.277 回答
7

你不能像这样打印放气的输出。它不是空终止的。你也不能勉强。

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

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

请参阅deflate 调用下的文档

这是您修改后的代码。请注意,如果您要压缩的不是字符串,则需要更改此内容,并且还可以使用不带终止零的字符串进行压缩,并在解压缩后将其添加回来。

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);
于 2011-09-24T16:41:19.633 回答
3

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

于 2011-09-24T18:53:49.603 回答