我正在学习LZ77压缩,我看到当我找到重复的字节字符串时,我可以使用<distance, length>
形式的指针,以及“&lt;”,“,”, “&gt;” 中字节是保留的。所以...如何压缩具有这些字节的文件,如果我不能压缩这些字节,但是不能通过不同的字节改变它(因为解码器将无法读取它)。有办法吗?或解码器只解码是否有一个确切的<d, l>
字符串? (如果存在,那么想象一下,如果通过共识,我们在文件中找到这些字节。会发生什么?)
谢谢!
答案 0 :(得分:1)
LZ77是关于在解压缩缓冲区中引用字符串的长度和距当前位置的距离。但是你如何对这些反向引用进行编码呢? LZ77的许多实现都以不同的方式实现。
但你是对的,必须有一些方法来区分&#34;文字&#34; (未压缩的数据片段意图被复制&#34;按照#34;从输入到输出)来自&#34;反向引用&#34; (从已经未压缩的部分复制而来。)
一种方法是将一些角色保留为&#34;特殊&#34; (所谓的&#34;转义序列&#34;)。您可以按照这样做的方式执行此操作,即使用<
标记反向引用的开头。但是如果它是文字,你还需要一种输出<
的方法。你可以这样做,例如,通过确定在<
之后另一个<
,然后它意味着文字,你输出一个<
。或者,您可以确定,如果在<
之后立即>
,之间没有任何内容,那么这不是后向引用,因此您只需输出{{1} }。
它也不是编码这些反向引用的最有效方法,因为它使用几个字节来编码反向引用,因此它仅对引用长于这几个字节的字符串有效。对于较短的反向引用,它将使数据膨胀而不是压缩它们,除非您确定匹配的数量短于几个字节,而不是生成反向引用。但同样,这意味着压缩增益会降低。
如果仅压缩普通的旧ASCII文本,则可以采用更好的编码方案,因为ASCII在一个字节中仅使用8位中的7位。因此,您可以使用最高位来指示反向引用,然后将剩余的7位用作长度,将下一个字节(或两个)用作反向引用的距离。通过这种方式,您可以通过检查其最高位来确定下一个字节是文字ASCII字符还是后引用。如果为0,则按原样输出字符。如果为1,则使用以下7位作为长度,并读取接下来的2个字节以将其用作距离。这样每个反向引用都需要3个字节,因此您可以有效地压缩文本文件,重复序列长度超过3个字符。
但是还有更好的方法可以做到这一点,它可以提供更多的压缩:你可以用可变长度的位代码替换你的字符,这样可以使出现频率更高的字符具有最短的代码,那些稀有的代码会有更长的代码。为了实现这一点,这些代码必须是所谓的&#34;前缀代码&#34;,因此没有代码将是某些其他代码的前缀。当您的代码具有此属性时,您始终可以通过按顺序读取这些位来区分它们,直到您解码其中的某些位。然后你可以确定你通过阅读更多位来获得任何其他有效项目。下一位总是启动另一个新序列。要生成此类代码,您需要使用霍夫曼树。然后,您可以将所有字节和不同长度的引用连接到一个这样的树中,并根据它们的频率为它们生成不同的位代码。当你尝试解码它们时,你只需要读取这些位,直到你到达其中一些元素的代码,然后你就确定它是一个字面字符的代码还是反向引用的代码长度。在第二种情况下,然后读取一些额外的位用于反向引用的距离(也用前缀代码编码)。这就是DEFLATE压缩方案的作用。但这是另一个故事,您将在@MarkAdler提供的RFC中找到详细信息。
答案 1 :(得分:0)
如果我理解你的问题,那就毫无意义了。 LZ77压缩器的未压缩输入没有“保留字节”。您需要简单地对文字和长度/距离对进行编码。