【问题标题】:deflate and inflate (zlib.h) in CC中的放气和膨胀(zlib.h)
【发布时间】:2011-11-24 07:28:49
【问题描述】:

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

【问题讨论】:

  • 你问是因为它不起作用吗?您是否收到某种错误消息?
  • @larsks 它编译时没有警告,但我想知道我选择的函数和定义是否有意义,或者我是否应该使用其他函数和定义。
  • 知道了。感谢您澄清您的问题。

标签: c compression zlib deflate


【解决方案1】:

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 可能很糟糕,但它指向了一个令人麻木的解决方案,它始终是首选。 compress()uncompress() 是你能得到的最简单的形式,而且你可以充分地展示它。
  • 这个实用方法的问题是您需要以某种方式知道未压缩内容的大小...:/
  • 在这种情况下,您可以对未压缩的内容使用 sizeof()。这是 compress() 和 uncompress() 方法的基本用法,这是一个好的开始,但还有更有效的技术。
【解决方案2】:

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

由于您的输入是一个字符串,尽管您可能只想传递字符串的内容,包括空终止符。所以将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);

【讨论】:

    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-08-29
      • 2010-11-09
      • 2021-03-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-24
      • 1970-01-01
      相关资源
      最近更新 更多