LZMA 解压算法如何工作?

How LZMA decompression algorithm works?

我无法理解 lzma 解压缩算法的工作原理,更准确地说是这个函数

int res = LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, 
        const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode);

这是一个无限循环,SizeT *destLen 和 SizeT *srcLen 的大小固定,大小相等,逻辑上 destLen(未压缩数据) 应该大于 srcLen(压缩数据) 并具有预定义的比率,我不明白它如何在相同大小下工作,或者它可以接受任何大小,然后它有一个临时缓冲区,可以存储数据并用它的方法处理它们。

这个功能确实不好用。它专为增量减压而构建。因此设想的用例是这样的:

  • 程序从文件等源中读取压缩数据。数据以块的形式读取,例如一次 1000 个字节。
  • 每个块都被解压缩到一个缓冲区中。缓冲区通常更大,例如2000 字节。解压缩块后,目标缓冲区将部分填充数据,例如1738 字节。
  • 对于每个块,解压缩后的数据将被进一步处理,例如写入文件。

解压缩文件并将结果写入另一个文件的简化代码如下所示:


file_in = open_file(...);
file_out = open_file(...);
while (!eof(file_in)) {
   len_in = read(file_in, buf_in, 1000);
   len_out = decompress(buf_in,len_in, buf_out, 2000);
   write(file_out, buf_out, len_out);
}
close(file_in);
close(file_out);

所以LzmaDec_DecodeToBuf的相关参数为:

  • dest:指向目标缓冲区的指针
  • destLen:指向目标长度的指针。调用者将长度设置为分配的缓冲区大小。 LzmaDec_DecodeToBuf 更新长度以包含解压缩数据的长度。
  • src: 指向源缓冲区的指针
  • srcLen:指向源长度的指针。调用者将长度设置为缓冲区中压缩数据的长度。 LzmaDec_DecodeToBuf 更新长度以包含已处理的字节数。

srLen 可能很棘手。在大多数情况下,将处理传递给该函数的所有数据。但如果解压后的数据不适合目标缓冲区,它只会处理部分数据。因此需要将解压缩的数据写入文件以释放目标缓冲区,并且需要使用剩余数据再次调用该函数。这已从简化代码中省略。

另一个遗漏是定稿。在输入文件的末尾,可能需要使用不同的完成模式最后一次调用 LzmaDec_DecodeToBuf