【问题标题】:cannot compress stream of data setting a dictionary with zlib无法使用 zlib 压缩数据流设置字典
【发布时间】:2023-06-21 22:29:01
【问题描述】:

我一直试图通过修改 zpipe.c 示例在 zlib 中设置字典。即,我有一个包含 32768 个字符的文件,我想将其转换为字典。所以我修改了zpipe(http://www.zlib.net/zpipe.c)。

在 def() 函数上,我补充说:

char dict[32768];
FILE *fd = fopen("dictB.txt", "r");
ssize_t test = fread(dict, 32768, 1, fd);
int lenDict = (int) sizeof(dict);
fclose(fd);

在 deflateInit() 之后,我添加了以下内容

ret = deflateSetDictionary(&strm, (const Bytef*) dict, lenDict);

为了更好的衡量,我在调用 deflate() 之前添加了 deflateSetDictionary 和每个点

在 inf() 函数上,我添加了相同的字典(为了完整性而重复):

char dict[32768];
FILE *fd = fopen("dictB.txt", "r");
ssize_t test = fread(dict, 32768, 1, fd);
int lenDict = (int) sizeof(dict);
fclose(fd);

在 inflate() 调用之后,我修改了 zpipe.c 使其可以接受字典调用:

ret = inflate(&strm, Z_NO_FLUSH);
if (ret==Z_NEED_DICT){
   ret = inflateSetDictionary(&strm, (const Bytef*) dict, lenDict); 
}
assert(ret != Z_STREAM_ERROR);  /* state not clobbered */
switch (ret) {
 case Z_DATA_ERROR:
 case Z_MEM_ERROR:
    (void)inflateEnd(&strm);
    return ret;
}

现在,运行压缩后

$ ./zpipe < file.txt > file.gz

然后一切正常运行

但是当我尝试解压时

$ ./zpipe -d < file.gz > file.dec.txt

然后我得到一个与Z_DATA_ERROR相关的错误:

zpipe: invalid or incomplete deflate data

执行 deflateSetDictionary 调用时不会出现此错误。我知道这个错误与 deflateSetDictionary 有关,并且可能在使用缓冲区实现时,因为在使用字典运行其他示例时没有错误(例如http://www.chuntey.com/Source/Zlib/example.c

【问题讨论】:

  • 这是什么意思:“为了更好的衡量,我在调用 deflate() 之前添加了 deflateSetDictionary 和每个点”? deflateSetDictionary 只能调用一次,紧跟在deflateInit 之后。
  • 这一行的实例:'int lenDict = (int) sizeof(dict);'这将始终返回 32768,无论 dict[] 数组的内容如何
  • @MarkAdler,我一开始也是这么想的,但后来手册说:“使用 zlib 格式时,必须在 deflateInit、deflateInit2 或 deflateReset 之后以及任何 deflate 调用之前立即调用此函数.",其中最后一部分的措辞我觉得有些不清楚。我最初也尝试过只打一次电话,但紧随 deflateInit... 会再试一次。
  • @user3629249,字典的字节数也是32768,但是你说得对,我需要修改为strlen()
  • inflateSetDictionary() 之后,您需要再次运行inflate()。否则你会掉出内部循环并覆盖已读取的输入。

标签: c dictionary compression zlib deflate


【解决方案1】:

inflateSetDictionary() 之后,您需要再次运行inflate()。否则,您将退出内部循环并覆盖已读取的输入。 ——马克·阿德勒

【讨论】: