【问题标题】:Adding header to zlib compressed file将标头添加到 zlib 压缩文件
【发布时间】:2018-10-04 04:26:04
【问题描述】:

我正在尝试使用 zlib 压缩(压缩?)文本文件中的数据。 当我压缩文件时它似乎工作,但我试图预先 带有自定义标头的 zlib 压缩文件。文件和标题 应该压缩。但是,当我添加标题时, 压缩(放气)文件比预期的要短得多 输出为无效的 zlib 压缩对象。

代码运行良好,直到我在 XXX cmets 下面。

“FILE *source”变量是一个示例文件,我通常使用 /etc/passwd 并且“char *header”是“blob 2172\0”。 没有标头块,输出为 904 字节且可压缩 (可解压缩),但带有标头的只有 30 个字节。 它也作为一个无效的 zlib 对象出现,其标头块为 代码。

我犯错误的任何想法,特别是为什么输出是 标题无效且较短?

如果相关,我将在 FreeBSD 上写这篇文章。

#define Z_CHUNK16384
#define HEX_DIGEST_LENGTH       257

int
zcompress_and_header(FILE *source, char *header)
{
int ret, flush;
z_stream strm;
unsigned int have;
unsigned char in[Z_CHUNK];
unsigned char out[Z_CHUNK];

FILE *dest = stdout; // This is a temporary test

strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
ret = deflateInit(&strm, Z_BEST_SPEED);
//ret = deflateInit2(&strm, Z_BEST_SPEED, Z_DEFLATED, 15 | 16, 8,
Z_DEFAULT_STRATEGY);

if (ret != Z_OK)
     return ret;

/* XXX Beginning of writing the header */

strm.next_in = (unsigned char *) header;
strm.avail_in = strlen(header) + 1;

do {
     strm.avail_out = Z_CHUNK;
     strm.next_out = out;
     if (deflate (& strm, Z_FINISH) < 0) {
          fprintf(stderr, "returned a bad status of.\n");
          exit(0);
     }
     have = Z_CHUNK - strm.avail_out;
     fwrite(out, 1, have, stdout);
} while(strm.avail_out == 0);

/* XXX End of writing the header */

do {
     strm.avail_in = fread(in, 1, Z_CHUNK, source);
     if (ferror(source)) {
          (void)deflateEnd(&strm);
          return Z_ERRNO;
     }

     flush = feof(source) ? Z_FINISH : Z_NO_FLUSH;
     strm.next_in = in;

     do {
          strm.avail_out = Z_CHUNK;
          strm.next_out = out;
          ret = deflate(&strm, flush);
          have = Z_CHUNK - strm.avail_out;
          if (fwrite(out, 1, have, dest) != have || ferror(dest)) {
               (void)deflateEnd(&strm);
               return Z_ERRNO;
          }
     } while(strm.avail_out == 0);

} while (flush != Z_FINISH);

} // End of function

【问题讨论】:

  • 一些问题,澄清一下:1)你定义了“#define Z_CHUNK16384”,我想它应该是“#define Z_CHUNK 16384”。如果 Z_CHUNK 在别处定义,程序会编译,但会使用意外的块大小。
  • 2) 您在标头上使用 strlen。标头是空终止的字符串吗?
  • Z_CHUNK 被称为 CHUNK,在 zlib 文档的 zpipe.c 示例中定义为 16384。仅通过了解代码,我就知道标头不为空,但我认为您需要添加错误检查。
  • 好的,我只是想指出,在第 1 行的#define 中的“Z_CHUNK”和“16384”之间应该有一个空格,否则你实际上并没有定义宏“Z_CHUNK” ,但“Z_CHUNK13384”。

标签: c zlib


【解决方案1】:

deflate 不是存档器。它只压缩一个流。一旦流用尽,您的选择将非常有限。手册清楚地说明了

如果参数 flush 设置为 Z_FINISH,则处理挂起的输入,刷新挂起的输出,如果有足够的输出空间,deflate 将返回 Z_STREAM_END。如果 deflate 返回 Z_OK 或 Z_BUF_ERROR,则必须再次调用此函数并使用 Z_FINISH 和更多输出空间(更新的avail_out)但没有更多输入数据,直到它返回 Z_STREAM_END 或错误。 deflate 返回 Z_STREAM_END 后,唯一可能对流进行的操作是 deflateReset 或 deflateEnd。

但是,您在 Z_FINISH 标头之后为文件调用 deflate,而 zlib 的行为不可预测。可能的解决方法是根本不使用Z_FINISH 作为标头,并让对方明白解压缩字符串中的第一行是标头(或强加一些双方都理解的归档协议)。

【讨论】:

  • 感谢您的精彩评论。我阅读了手册页和您的评论 - 所以不要在标题中使用 Z_FINISH。在剩余的选项(Z_NO_FLUSH、Z_PARTIAL_FLUSH、Z_SYNC_FLUSH、Z_FULL_FLUSH、Z_BLOCK 和 Z_TREES)中,我应该使用什么?
  • @FarhanYusufzai 来自 zlib 手册:“通常,参数 flush 设置为 Z_NO_FLUSH,它允许 deflate 决定在产生输出之前要累积多少数据,以最大限度地压缩。 i>"
【解决方案2】:

您对deflate() 的第一次调用应使用Z_NO_FLUSH,而不是Z_FINISHZ_FINISH 仅应在通过 deflate() 调用提供最后一个要压缩的数据时使用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多