C语言 在 C 中放气和充气(zlib.h)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7540259/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 09:42:26  来源:igfitidea点击:

deflate and inflate (zlib.h) in C

ccompressionzlibdeflate

提问by Jane Watson

I am trying to implement the zlib.h deflate and inflate functions to compress and decompress a char array (not a file).

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

I would like to know if the following syntax is correct ? Am I missing something or defined something incorrectly ?

我想知道以下语法是否正确?我是否遗漏了某些东西或错误地定义了某些东西?

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);

采纳答案by Guy Sirton

You can't printf the deflated output like this. It's not null terminated. You can't strlen it either.

你不能像这样打印压缩的输出。它不是空终止。你也无法控制它。

Since your input is a string though you probably do want to only pass the content of the string including the null terminator. So set avail_in to strlen(a) + 1.

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

You need to examine the next_out and avail_out fields after you call deflate to see how much data was written to the output buffer.

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

See documentation hereunder the deflate call.

见文档这里放气号召下。

Here's your modified code. Note if you're compressing something that is not a string you'll need to change this and also with strings you may compress without the terminating zero and add it back after decompressing.

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

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);

回答by Yehia Hafez

zlib already has a simple inflate/deflate function you can use.

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);

When in doubt, check out the zlib manual. My code is crappy, sorry =/

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

回答by Necrolis

The zpipe example (http://zlib.net/zpipe.c) pretty much covers it, just remove the file ops(the f prefixed function), and you replace inand outwith your in-memory buffers, though it may be enough to only replace inor keep the buffers as-is depending on you usage. Just note that you will need to make your outbuffer resizeable to account for decompression of arbitrarily sized data, if you are planning on having unknown sized chunks

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