Quicklz压缩算法

Quicklz压缩算法


  算法官网地址:http://www.quicklz.com/index.php

适用于stm32做的加、解压缩,目前有c,c++,java 版

以前对压缩算法一无所知,只是知道哈弗曼编码能做这种事情,但是感觉这样的方法奇慢无比。昨天下午看了下号称世界上最快的压缩算法Quicklz,对压缩的基本思路有了一定的了解。一般的压缩程序的要求读入文件之后以便压缩一边输出,而不是去先分析整个文件中的情况之后才做决定采取哪种算法。

  Quicklz也不例外也是争取利用文件中重复出现的字节来进行压缩,管理结构如下:

在压缩的过程中不断地读入3个字节,然后根据这3个字节得到一个hash值,根据这个hash值就可以找到offset,这个offset就是上次这个hash值出现的位置,而通过cache可以判断出这次出现的和最近一次出现相同hash值的时候的3个字节是不是相同(可能hash相同而实际的值不同)。

  如果相同的长度在3到18之间,那么这些情况可以用4个位来表示。而大于18小于255的情况则需要8位来表示,刚才用于表示长度的低4为则全部变为0,以区别两种情况。在Level=1的时候就只有这两种情况了。在压缩的过程中用4个字节来记录压缩操作,如果有压缩则为1,否则为0。下面是level=1时候的情况:

  level=1的时候有个很明显的问题是只记录了一个hash相同时候的cache,这样的话只能等到与上次的值相同才能压缩,而与以前的值相同也不行。在level=2和level=3的时候弥补了这个缺陷,但是代价就是压缩的时间变长。在level=2的时候保存了4个offset(相同hash的位置),然后在这四个中取到重复字节长度最长的一个作为压缩选项(这个值保存在最低的2位中),而重复的长度信息保存在接下来的3个位中(如果够的话,不然初始化这3个位为0,在hash值后面的一个字节中保存),其他的地方就和level=1的时候相同了。压缩后文件的格式如下:

  在上面的情况中我们发现如果是3个字节相同的话只能把它压缩成2个字节。而在level=3的时候弥补了这个缺陷,在level=3的时候与前两个的不同之处是最低的两位统一作为标志,记录进行了什么操作,具体的代码如下:

复制代码
if(matchlen == 3 && offset <= 63)
{
*dst = (unsigned char)(offset << 2);
dst++;
}
else if (matchlen == 3 && offset <= 16383)
{
ui32 f = (ui32)((offset << 2) | 1);
fast_write(f, dst, 2);
dst += 2;
}
else if (matchlen <= 18 && offset <= 1023)
{
ui32 f = ((matchlen - 3) << 2) | ((ui32)offset << 6) | 2;
fast_write(f, dst, 2);
dst += 2;
}
else if(matchlen <= 33)
{
ui32 f = ((matchlen - 2) << 2) | ((ui32)offset << 7) | 3;
fast_write(f, dst, 3);
dst += 3;
}
else
{
ui32 f = ((matchlen - 3) << 7) | ((ui32)offset << 15) | 3;
fast_write(f, dst, 4);
dst += 4;
}
复制代码

虽然最后的两种情况的最低两位都是11,但是从下面的格式图中一眼就能看出区别(对应上面的代码看):

  这里知道了文件被压缩后保存的存储格式,下面考虑一下怎么解压。在level=3的时候解压方法还是很好理解的。但是在level=1和level=2的时候怎么解压呢?毕竟压缩文件中只是存储了hash值,而没有指出重复的字节串,甚至连offset都没有给出。这里其实很好理解,因为第一次遇到一个hash的时候当然是不会去压缩它的,那么在解压程序中我们就得到了offset的值,并且随着解压的进行,hash和offset的值与压缩时候的变化是相同的,所有不必保存这些值也能保证正确的解压。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
引用\[1\]中提到了Quicklz算法是一种快速的压缩算法。一般的压缩程序会在读入文件后立即进行压缩,而不是先分析整个文件再决定采用哪种算法。在解压方面,对于level=3的情况,解压方法相对容易理解。但是对于level=1和level=2的情况,解压方法稍微复杂一些。因为压缩文件中只存储了哈希值,没有指明重复的字节串,甚至没有给出偏移量。但是在解压程序中,我们可以根据第一次遇到哈希值时不进行压缩的原则,得到偏移量的值。随着解压的进行,哈希值和偏移量的变化与压缩时的变化是相同的,因此不需要保存这些值也能正确解压。\[2\] 根据引用\[3\]中的代码片段,我们可以看到Quicklz算法的解压过程中使用了不同的解压方式,根据匹配长度和偏移量的不同,采用了不同的解压方法。具体来说,当匹配长度为3且偏移量小于等于63时,解压方法是将偏移量左移2位后赋值给目标位置;当匹配长度为3且偏移量小于等于16383时,解压方法是将偏移量左移2位并加上1,然后使用fast_write函数将结果写入目标位置;当匹配长度小于等于18且偏移量小于等于1023时,解压方法是将匹配长度减去3左移2位,偏移量左移6位,再加上2,然后使用fast_write函数将结果写入目标位置;当匹配长度小于等于33时,解压方法是将匹配长度减去2左移2位,偏移量左移7位,再加上3,然后使用fast_write函数将结果写入目标位置;最后一种情况是匹配长度减去3左移7位,偏移量左移15位,再加上3,然后使用fast_write函数将结果写入目标位置。 因此,使用Quicklz算法进行解压时,根据匹配长度和偏移量的不同,采用不同的解压方法来还原原始数据。 #### 引用[.reference_title] - *1* *2* *3* [Quicklz压缩算法](https://blog.csdn.net/QQ576494799/article/details/108889946)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值