此问题可能不严格限于LZW算法,可能涵盖LZ77和LZ78的其他实现:
我一直在尝试编写一个涉及LZW字典编码方案的压缩/解压缩实用程序。 问题是我发现在编码阶段写出每个代码字(或“代码”)之后必须包含一个分隔符(空格)。 我一直这样做是因为我不能假设输出直接流到解码器,并且可以存储在压缩文件中以便稍后解码(在这种情况下,解码器需要一些方法来检测分离的内容)代码字 - 分隔符。
我最近被告知这是不必要的,并且解码器应该能够动态地“弄清楚”每次读取多少压缩文件,可能是基于先前读取的代码。这可以消除在每个代码之后插入额外字节的(代价高昂的)需求。
我只是不确定解码器如何解决这个问题。也许有人了解它的工作原理可以向我解释一下吗?感谢。
编辑:
字典是将“输入字符串”映射到整数(代码)的散列表,并且在读入更多输入数据时以通常的方式构建。字典被写出到压缩文件中。解码器从压缩文件中读取每个代码(整数),并查找其字典以查找要输出的关联字符串,或者如果该代码没有条目,则它会以通常的方式确定字符串应该是什么并更新它的字典。
“如果文件流式传输或存储,为什么会有所不同?” 如果编码器的输出一次一个代码地流到解码器,则解码器可以在接收它们时使用每个代码。但是如果编码器将所有代码写入文件(压缩文件),然后将该文件送入解码器,那么解码器如何知道一个代码的开始位置和另一个代码的开始位置。该文件只是一个混合的数字序列。
例如: 定界压缩文件:127 32 45 22 228 122 209 .... 非定界压缩文件:127324522228122209 ...
-Rob
答案 0 :(得分:2)
在LZW中,字典不与压缩文件一起存储。 (或者字典是文件,依赖于您的观点。)写入文件的每个值都根据其位置具有预定义的位宽。例如,它可以作为9位字典索引对,然后是8位数据开始,直到索引在切换到10位索引时耗尽(发生在精确位置)。
详细信息取决于您如何实施压缩。有些人做一个恒定的12位索引。但在任何情况下都不需要额外的分隔符。
此外,由于数据未在8位边界上对齐,如果您尚未正确读取数据,则无法检测分隔符!
编辑:
如果您希望LZW压缩算法实际生成较小的数据而不是输入,那么您应该做几件事。
首先,您必须将文件写为二进制而不是文本。将其写为文本将扩展而不是缩小文件的大小。值127可以以二进制(01111111)存储在单个字节中,但需要四个字节的UTF-8和一个分隔空格(“127”= 00110001 00110010 00110111 00100000)。
其次,LZW设计用于处理大于一个字节但小于两个字节的代码值,因此必须进行一些比特操作才能正确输出数据。单个字节仅足以编码前256个隐式定义的表条目。另一位将为您提供另外256个条目,但9位索引表中的条目很快就会耗尽。使用12位,您可以获得4096个表条目,这是一个合理的表大小。如果您要使用两个完整字节,那么您将拥有一个包含65 K条目的相当大的表。这样做的问题在于,如果你没有使用表空间的全部容量,那么你就是在浪费时间。输出中有很多位总是为零,这对你的压缩率来说非常糟糕。
第三,流编码器/解码器不能一次执行单个值,因为编码数据与字节边界重叠。如果使用恒定的12位代码大小,则可以一次处理两个编码值的一些倍数。但一般来说,该算法旨在使用完整的文件。
答案 1 :(得分:1)
使用LZW,在读取文件时生成码本,这样就不需要分隔符了。当每个字符添加到LZW输出时,它将从8位转换为更高的位置(通常为10或12位),以便为代码簿提供空间。例如:
banana
在LZW中,b
已经在码本中(参考文献2),所以转到ba
。 ba
不在代码簿中,因此请添加它。
目前输出
带有码本的 ba
27 = ba
(1-26是a-z的索引)
接下来保留a
并读取n
- > an
。这也不在代码簿中,所以它被添加。
目前输出
带有码本的 ban
27 = ba
28 = an
重复直到结束。结果是:
带有码本的 bana29
27 = ba
28 = an
29 = na
无需添加分隔符,因为单词bana29
已解码,29
的查找已存在于代码簿中。
我希望这有助于解释为什么不需要使用LZW进行清除