我正在尝试使用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
答案 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_FINISH
。 Z_FINISH
仅在deflate()
调用提供了最后一个要压缩的数据时使用。