将标头添加到zlib压缩文件

时间:2018-10-04 04:26:05

标签: c zlib

我正在尝试使用zlib压缩(压缩?)文本文件中的数据。 压缩文件时似乎可以正常使用,但是我想在前面添加 具有自定义标头的zlib压缩文件。文件和标题 应该被压缩。但是,当我添加标题时, 压缩(缩小)的文件比预期的要短得多,并且 作为无效的zlib压缩对象。

代码效果很好,直到我在 下面有XXX条评论。

“ 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

2 个答案:

答案 0 :(得分:1)

deflate不是存档器。它仅压缩流。一旦流耗尽,您的选择将非常有限。手册明确指出

  

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

但是,您在标题deflate之后调用了文件Z_FINISH,并且zlib的行为异常。可能的解决方法是根本不使用Z_FINISH作为标头,而让另一端了解解压缩的字符串的第一行是标头(或强加双方都理解的某些归档协议)。

答案 1 :(得分:0)

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