精华内容
下载资源
问答
  • deflate-decompressor-c 不工作! 根据尝试解压缩Deflate
  • Java中的简单DEFLATE实现 山脊灌木丛(21112211) 用法 java GZCompressor -vpcd [in-file] [out-file] 选项 描述 -v 详细模式 -p 显示进度 -C 压缩 -d 解压缩 Deflater.java中的可配置值 MODE (0 =不压缩,1 =...
  • node-deflate:非同期でdeflate展开。それだけ
  • deflate = require ( 'permessage-deflate' ) ; var exts = new Extensions ( ) ; exts . add ( deflate ) ; 可以配置扩展名,例如: var Extensions = require ( 'websocket-extensions' ) , deflate = require...
  • deflate-decompressor-c 不工作! 根据尝试解压缩Deflate
  • deflate树与deflate编码

    2016-01-25 01:18:00
    关于deflate树,能搜到的资料非常少,这个概念来自gzip的压缩算法,是由huffman树转变过来的。这里简单记录下deflate树的生成过程以及deflate编码。 假设以5 8 9 10 14 15,建立一颗huffman树,可以是这个样子的: ...

    关于deflate树,能搜到的资料非常少,这个概念来自gzip的压缩算法,是由huffman树转变过来的。这里简单记录下deflate树的生成过程以及deflate编码。

    假设以5 8 9 10 14 15,建立一颗huffman树,可以是这个样子的:

                      61
               /            \
              27              34
          /       \       /        \
         14       13     15        19
                /   \            /   \
               5     8          9    10

     也可以交换任意结点的两棵子树

                     61
               /            \
              34              27                           
          /       \       /         \
         15      19      14        13
               /   \              /   \
              9   10             5    8

    交换的过程虽然会改变叶子结点的huffman编码,但是,不会改变huffman树的带权路径和,也不会改变每个叶子结点的编码长度。基于这一点,我们可以做个更特殊的变换,每一层,让非叶子结点排在右边,叶子结点排在非叶子结点的左边。上面这棵树的变换之后如下:

                      61
               /            \
              34              27                           
          /       \       /         \
         15        14    19         13
                       /   \      /   \
                       9   10     5    8
    经过变换后,上面这颗树就称为deflate树。同样,deflate树虽然改变了结点的huffman编码,但是没有改变每个元素的编码长度。在gzip压缩中的语义就是没有改变压缩率。
    上面的变化用语言表达起来不好理解,再用一个例子说明:
    假设下面是一个huffman树:
                      A
               /             \
              B              C                           
          /       \       /      \
          D        E      F      G
                 /   \  /   \
                 G   H I    J
               /   \                 
               K   L                        
                 /  \
                 M  N 
    转化为deflate之后,如下:
               A
               /             \
              B              C                           
          /       \       /         \
          D        G      F          E
                       /   \       /   \
                       I   J      H    G
                                     /   \                 
                                     K   L                        
                                       /  \
                                       M  N
    那么,转换为deflate树有什么好处呢?
    这涉及到码表的记录。所谓的码表就是元素及其对应的编码。
    先看下正常huffman编码下码表的记录
    还是以5 8 9 10 14 15为集合,以下面这颗huffman树为例:
                     61
               /            \
              34              27                           
          /       \       /         \
         15        19     14         13
                  /   \             /   \
                 9   10            5    8
    假设走左为0,走右为1,那么码表就是:
    15          14              9             10            5            8
    00          10             010         011           110        111
    为了能够解码,我们必须把这个码表记录下来。
     
    再看下转换为deflate树后,如何记录
    上面这颗树转换后如下:
                     61
               /            \
              34              27                           
          /       \       /         \
         15        14    19         13
                        /   \      /   \
                        9   10     5    8
    假设还是走左为0,走右为1。转换后元素的编码改变了,码表应该如下:
    15          14              9             10            5            8
    00          10             100         101           110        111
    虽然元素的编码变化了,但不要紧,只要我们记录如上这个码表,还是能把数据还原的。
    前边说过,deflate虽然改变了编码,但是每个元素的编码长度是不变的,这个时候,可以只记录每个元素的编码长度,就可以在解码的时候把数据还原。现在,码表这么记录,每一层,从左往右记录叶子结点的编码长度,层次按从上到下。先记录第2层(根节点为第0层)的两个叶子,再记录第三次的4个叶子,码表如下:
    15          14                 9         10            5            8
     2            2                 3           3             3            3
    先别管如何根据这个码表解码,先对比下这两种记录法,会发现,下面这种码表记录要比上面的码表记录节省比特,2的二进制位10   ,  3的二进制位11   ,总的比特位6*2=12。
    而上边的编码总长度为2+2+3+3+3+3=16(15、14的编码长度2,9、10、5、8的编码长度为3)。这并不是偶然,因为一个元素的编码的长度(10的编码长度为3)所占的二进制比特位(10的编码长度3,占二进制2位)肯定小于等于编码所占的长度(10的编码长度3)。
    这就是记录码长的好处,为什么要这么计较这一丁点的比特呢,要知道,deflate树是用于压缩算法的,而且这样做并不复杂,何乐而不为?

     

    现在再来说一下,有了这个码表如何解码,解码是编码的逆过程,所以,先看deflate树的编码

    deflate树,编码方式为:

    第n层的最左边的叶子结点的编码=((第n-1层的最左边的叶子结点的编码 )+  (第n-1层的叶子结点数))<< 1 。

    第n层,后一个叶子结点的编码 = 前一个叶子结点的编码+1

    还以下面这颗树为例:

                     61
               /            \
              34              27                           
          /       \       /         \
         15        14    19         13
                       /   \      /   \
                      9   10     5    8
    15的编码为00
    那么9的编码 = (上一层最左边的叶子结点15的编码+上一层的叶子结点数2)<<1
                     =   (00 + 10)<<1
                     =    100
    10的编码 = 9的编码+1 = 101
    5的编码  = 10的编码+1 = 110
    8的编码  = 5的编码+1 = 111
     
    现在可以说解码过程了,码表先搬下来:
    15          14                 9         10            5            8
     2            2                 3           3             3            3
    由于这个码表的记录方法是每层叶子结点从左到右,并且层次从上到下的方式,而且,会发现,编码长度就是叶子所在的层次(假设根节点为第0层)。所以,第二层开始出现了第一个叶子结点,第一个叶子结点一定是一直往左的。那么根据编码规则15的编码就是00,14的编码是01,9的编码是(00+2)<<1 = 100...
     
    这就是deflate树与deflate编码。事实上,在gzip中,deflate树的码表并不是这么记录,但deflate树的编码和解码思想是这样的。上面的码表了记录元素及其对应的码长,但在gzip中,为了更好压缩效果,并不会记录元素,而是直接记录元素的编码长度,用一个长度序列来表示码表。如果想了解其实现,应该去看看gzip的源码,gzip的源码非常精彩,极客思想无处不在,简直让人叹为观止。

    转载于:https://www.cnblogs.com/zengzy/p/5156130.html

    展开全文
  • RFC1951 deflate格式

    2016-07-31 15:26:03
    deflate压缩算法基本格式介绍
  • Dos-Deflate

    2021-02-03 14:10:10
    DoS-Deflate是一款免费的用来防御和减轻DDoS攻击。它通过netstat监测跟踪创建大量网络连接的IP地址,在检测到某个结点超过预设的限制时,该程序会通过APF或iptables禁止或阻挡这些IP. 安装 wget ...

    Dos-Deflate是一款免费的用来防御和减轻DDoS攻击。它通过netstat监测跟踪创建大量网络连接的IP地址,在检测到某个结点超过预设的限制时,该程序会通过APF或iptables禁止或阻挡这些IP.

    安装

    wget https://github.com/jgmdev/ddos-deflate/archive/master.zip -O ddos.zip
    unzip ddos.zip
    cd ddos-deflate-master
    ./install.sh

    配置

    配置文件是 /usr/local/ddos/ddos.conf ,默认有如下配置

    FREQ=1
    NO_OF_CONNECTIONS=150
    APF_BAN=1
    KILL=1
    EMAIL_TO=”root”
    BAN_PERIOD=600

    IP地址白名单:/usr/local/ddos/ignore.ip.list

    卸载

    cd ddos-deflate-master
    ./uninstall.sh

    DDoS deflate 工作原理

    每分钟检测一次IP连接状况,当某些IP连接超过配置脚本限制的连接数,程序会自动禁止这些IP一段时间,以达到防御攻击的目的

    DDoS deflate官方网站:http://deflate.medialayer.com/

    Installation 安装

    wget http://www.inetbase.com/scripts/ddos/install.sh 
    chmod 0700 install.sh 
    ./install.sh

    Uninstallation 卸载

    wget http://www.inetbase.com/scripts/ddos/uninstall.ddos 
    chmod 0700 uninstall.ddos 
    ./uninstall.ddos

    检查是否遭到ddos攻击命令

    netstat -ntu | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -n

    DDoS deflate的默认配置位于/usr/local/ddos/ddos.conf ,内容如下:

    ##### Paths of the script and other files 
    PROGDIR="/usr/local/ddos" 
    PROG="/usr/local/ddos/ddos.sh" 
    IGNORE_IP_LIST="/usr/local/ddos/ignore.ip.list"  //IP地址白名单 
    CRON="/etc/cron.d/ddos.cron"    //定时执行程序 
    APF="/etc/apf/apf" 
    IPT="/sbin/iptables"  
    ##### frequency in minutes for running the script 
    ##### Caution: Every time this setting is changed, run the script with --cron 
    #####          option so that the new frequency takes effect 
    FREQ=1   //检查时间间隔,默认1分钟  
    ##### How many connections define a bad IP? Indicate that below. 
    NO_OF_CONNECTIONS=150     //最大连接数,超过这个数IP就会被屏蔽,一般默认即可  
    ##### APF_BAN=1 (Make sure your APF version is atleast 0.96) 
    ##### APF_BAN=0 (Uses iptables for banning ips instead of APF) 
    APF_BAN=1        //使用APF还是iptables。推荐使用iptables,将APF_BAN的值改为0即可。  
    ##### KILL=0 (Bad IPs are'nt banned, good for interactive execution of script) 
    ##### KILL=1 (Recommended setting) 
    KILL=1   //是否屏蔽IP,默认即可  
    ##### An email is sent to the following address when an IP is banned. 
    ##### Blank would suppress sending of mails 
    EMAIL_TO="root"   //当IP被屏蔽时给指定邮箱发送邮件,推荐使用,换成自己的邮箱即可  
    ##### Number of seconds the banned ip should remain in blacklist. 
    BAN_PERIOD=600    //禁用IP时间,默认600秒,可根据情况调整

    试用了一会,感觉还不错,比我以前用的分析nginx日志封IP的脚本要好些,假如几个虚拟主机使用不同的网站日志,就必须运行几个分析日志的脚本,

    这个脚本就用一个就可以把整个服务器保护起来了。但这个也存在一些问题,刚开始的时候把mysql服务器给封掉了,搞的我手忙脚乱的解封,

    然后把mysql服务器IP添加白名单,谁知过会他过了段时间又把白名单删除了,又给mysql服务器封了,不得以卸载了一次。

    研究了一下代码才发现,他禁止的IP也添加到白名单里,然后解封的时候通过tmp目录里的unban.xxxxx文件将白名单里禁止的IP再删除,

    这样这个IP就不再受保护。所以我把mysql服务器IP添加白名单之后程序根据这个BAN_PERIOD=600 参数在10分钟后删除,所以就出现了你恢复他继续封的怪圈,白名单设置文件应该和禁止解禁这个IP记录文件分开就好了。

    使用心得:

    安装后第一时间要将白名单设置好,最好观察一段时间看是不是正常,以免一些和服务器需要保持连接的IP被封,比如mysql服务器,rsync备份服务器等等,这些机器往往都需要和网站服务器保持大量连接

    怎么查看被屏蔽 IP?

    iptables -L -n 命令可以查看被屏蔽的 IP

    另外假如采用CDN加速不适于用这脚本,cdn节点缓存服务器IP百分百会被他封掉。

    #防止SYN攻击 轻量级预防 
    iptables -N syn-flood 
    iptables -A INPUT -p tcp --syn -j syn-flood 
    iptables -I syn-flood -p tcp -m limit --limit 3/s --limit-burst 6 -j RETURN 
    iptables -A syn-flood -j REJECT
    展开全文
  • deflate算法总结

    2021-03-22 09:54:45
    Deflate是一种数据无损压缩算法,它广泛用于zip文件压缩以及png图片压缩。deflate结合了huffman编码和LZ77编码,流程如下: 1.LZ77算法,利用相邻数据的相关性对原始数据压缩,该模块输入为原始数据,输出为...

    参考资料:
    1.gzip压缩系列
    2.ZIP压缩算法详细分析及解压实例解释
    3.An Explanation of the Deflate Algorithm
    4.RFC1951

    1.deflate压缩

    Deflate是一种数据无损压缩算法,它广泛用于zip文件压缩以及png图片压缩。deflate结合了huffman编码和LZ77编码,流程如下:
    在这里插入图片描述

    • 1.LZ77算法,利用相邻数据的相关性对原始数据压缩,该模块输入为原始数据,输出为literal、distance-length数据对;
    • 2.huffman编码,对LZ77的结果分别进行数据统计生成huffman表,再对数据进行huffman编码。该模块的输入为literal和distance-length数据对,其中literal和length共用一个huffman表压缩,distance单独一个huffman表压缩。该模块的输出为两个huffman表以及经过huffman压缩后的数据;
    • 3.序列化、游程编码,huffman表数据可进一步用Huffman编码压缩。该模块的输入为两个huffman表,输出为该huffman表统计后生成的huffman表,以及压缩后的数据流。

    2.LZ77算法

    由于字符串有很多子串是重复出现的,LZ77压缩算法正是利用这一特点压缩数据的。压缩过程中,会从已压缩的数据中查找该字符是否在前面出现过,如果出现过,则只需保存该字符与以前出现字符的距离以及字符长度。其中已压缩的数据会有最大长度,如果超出该长度则滑动窗需要前移。

    当下一个需要压缩的字符序列能够在滑动窗口中找到, 这个序列会被两个数字代替: 一个是距离,表示这个序列在窗口中的起始位置离窗口的距离, 一个是长度, 字符串的长度。

    以如下数据为例:
    Blah blah blah blah blah!
    字符串开始于: ‘B’,‘l’,‘a’,‘h’,‘ ’and ‘b’, 再来看接下来的5个字符:
    在这里插入图片描述

    前面的字符可以和这5个字符完全匹配,且刚好从当前数据的前5个字符开始。我们可以用当前子串起始字符与匹配字符串的距离distance和匹配字符串长度length。

    目前数据是:
    Blah blah b
    压缩后的数据为
    Blah b[D=5,L=5]

    压缩还能继续进行, 对比这两个相同的字符串,它们各自的下一个字符都是‘1’, 所以我们可以把长度更新为6。如果我们继续比较,发现下一个, 下下一个, 下下下一个都是一样的。最终我们发现, 有18个字符相等。

    最终压缩的数据为:
    Blah b[D=5, L=18]!

    其中压缩后的数据‘Blah b’以及最后的‘!’与原始字符串完全一样,称为literal。因此压缩后的数据由三类元素构成literal、length、distance。

    LZ77算法的核心是在前面的历史数据中寻找重复字符串,同时重复现象是具有局部性的,它的基本假设是,如果一个字符串要重复,那么也是在附近重复,远的地方就不用找了,因此设置了一个查找数据的滑动窗口。LZ77滑动窗口是32KB,那么就是往前面32KB的数据中去找,这个32KB随着编码不断进行而往前滑动。

    把滑动窗口设置得很大,那样就有更大的概率找到重复的字符串,压缩率会更高吗?初看起来如此,找的范围越大,重复概率越大,不过仔细想想,可能会有问题,一方面,找的范围越大,搜索时计算量会增大,不利于工程实现;另一方面,找的范围越大,距离越远,也不利于对距离进行进一步压缩。

    3. huffman编码

    huffman编码是一种前缀编码,每一个元素都有一个对应码字,其中每个码字都不可能是其他码字的前缀。huffman编码的基本原理是出现概率高的字符用尽可能短的码字编码。

    以下面数据为例,
    3、6、4、3、4、3、4、3、5
    这个例子里,3出现了4次,4出现了3次,5出现了1次,6出现了1次。

    根据数据出现频次我们可以构建一个huffman树,如下图:
    在这里插入图片描述
    各数字及其编码后码字分别为0–>3;10–>4;110–>5;111–>6。

    上一章我们知道LZ77算法结果由三部分构成(literal、length、distance),以distance为例,LZ77中滑动窗大小固定为32K,也意味着distance的取值范围是1-32768。如果通过上面的方式,统计频率后将得到32768个码字,构建出来的huffman树会很大,不利于压缩存储。Deflate算法通过对huffman树增加一些特性使huffman码表更容易记录。

    3.1 deflate中huffman树的记录方式

    分析上面的例子,我们得到这个码表:
    0–>3;10–>4;110–>5;111–>6。

    码字中的0和1就是二进制的一个标志,互换一下其实根本不影响编码长度,所以,下面的码表也可以表示同样的符号。他们编码长度一样,只是码字不同。
    1–>3;00–>4;010–>5;011–>6。
    1–>3;01–>4;000–>5;001–>6。
    0–>3;11–>4;100–>5;101–>6。

    对比第一个和第二个例子,对应码树如下:
    在这里插入图片描述
    也就是说,我们把码树的任意节点的左右分支旋转(0、1互换),也可以称为树的左右互换,其实不影响编码长度。既然这些树的压缩程度都一样,那干脆使用最特殊的那棵树,只要规定了这棵树的特殊性,那么记录的信息就可以最少。

    不同的树当然有不同的特点,deflate选择的树就是左边那棵,这棵树有一个特点,越靠左边越浅,越往右边越深,是这些树中最不平衡的树。这棵树也称为Deflate树,对应的解压缩算法称为Inflate。

    按RFC1951总结的Deflate树相对于huffman树的新增特性:

    1. 同样位长的叶子节点的编码值为按字典顺序连续,右边的总比左边的大1;
    2. N+1位长最左边的叶子节点(也就是该层编码值最小的叶子节点)的值为N位长最右边叶子节点的值+1,然后左移以位,也就是code=(code+bl_count[N])<<1;

    基于以上原则,我们可以通过字符对应的huffman码字长度记录huffman表。比如,一个有效的码表是0–>3;10–>4;110–>5;111–>6。但只需要记录这个对应关系即可:
    3  4  5  6
    1  2  3  3

    也就是说,把1、2、3、3记录下来,解压时照着左边那棵树的形状构造一颗树,然后只需要1、2、3、3这些信息就可得到huffman码字是0、10、110、111。这就是deflate最核心的一点:这棵码树用码字长度序列记录下来即可。

    当然,只把1、2、3、3这个序列记录下来还不行,比如不知道111对应5还是对应6?所以,构造出树来只是知道了有哪些码字了,但是这些码字到底对应哪些整数还是不知道。

    前面已经说了,记录1、2、3、3还是记录1、3、2、3,或者3、3、2、1,其实都能构造出这棵树来,那么,我们可以选择一个特殊码字顺序记录,这个顺序就是按照整数由小到大的排列顺序,比如上面的3、4、5、6是整数大小顺序排列的,那么,记录的顺序就是1、2、3、3,而不是2、3、3、1。

    根据1、2、3、3这个信息构造出了码字,这些码字对应的整数一个比一个大,假如我们知道编码前的整数就是3、4、5、6这四个数,那就能对应起来了,不过实际情况到底是哪四个数字还是不知道。以distance为例,由于distance的范围是1-32768,那么就按照这个顺序记录。上面的例子1和2没有,那就记录长度0。所以记录下来的码字长度序列为:
    码字: 0、0、1、2、3、3、0、0、0、0、0、………
    对应数值:1、2、3、4、5、6、7、8、9、10、11、……

    这样就知道构造出来的码字具体对应哪个整数,但因为distance可能出现的数值有32768个,但实际出现的往往不多,中间会出现很多0(也就是根本就没出现这个距离),如果每个数字都编码,会有很多冗余数据,因此需要继续优化。

    3.2 distance的压缩方式

    每个distance肯定对应唯一一个码字,使用Huffman编码可以得到所有码字,但是因为distance可能非常多,虽然一般不会有32768这么多,但对一个大些的文件进行LZ编码,distance上千还是很正常的,所以这棵树很大,计算量、消耗的内存都容易超越了那个时代的硬件条件。Deflate算法把distance划分成多个区间,每个区间当做一个整数来看,这个整数称为Distance Code。当一个distance落到某个区间,则相当于是出现了那个Code,多个distance对应于一个Distance Code,Distance虽然很多,但Distance Code可以划分得很少,只要我们对Code进行Huffman编码,得到Code的编码后,Distance Code再根据一定规则扩展出来。我们分析过,越小的距离,出现的越多;越大的距离,出现的越少,所以这种区间划分不是等间隔的,而是越来越稀疏的,类似于下面的划分:
    在这里插入图片描述
    1、2、3、4这四个特殊distance不划分,或者说1个Distance就是1个区间;5,6作为一个区间;7、8作为一个区间等等,基本上,区间的大小都是1、2、4、8、16、32这么递增的,越往后,涵盖的距离越多。为什么这么分呢?首先自然是距离越小出现频率越高,所以距离值小的时候,划分密一些,这样可以对小的距离进行更精细地编码,使得其编码长度尽可能小;对于距离较大那些,因为出现频率低,所以可以适当放宽一些。另外,只要知道这个区间Code的码字,那么对于这个区间里面的所有distance,后面追加相应的多个比特(extra bits)即可,比如,17-24这个区间的Huffman码字是110,因为17-24这个区间有8个整数,于是按照下面的规则即可获得其distance对应的码字:
    17–>110 000
    18–>110 001
    19–>110 010
    20–>110 011
    21–>110 100
    22–>110 101
    23–>110 110
    24–>110 111

    这样需要进行Huffman编码的整数变少了,这棵huffman树不会太大,计算起来时间和空间复杂度降低,扩展起来也比较简单。当然,从理论上来说,这样的编码方式实际上将编码过程分为了两级,并不是理论上最优的,把所有distance当作一个大空间去编码才可能得到最优结果,不过还是那句话,工程实现的限制,在压缩软件实现上,我们不能用压缩率作为衡量一个算法优劣的唯一指标,其实耗费的时间和空间同样是指标,所以需要看综合指标。

    Distance划分为30个区间,左边的code表示该区间的编号,范围是0-29,共30个区间,这只是个编号,没有特别的含义,但Huffman就是对0-29这30个Code进行编码的,得到区间的码字;

    Extra bits表示distance的码字需要在Code的码字基础上扩展几位,比如0就表示不扩展,最大的13表示要扩展13位,因此,最大的区间包含的distance数量为8192个。

    Distance一列则表示这个区间涵盖的distance范围。
    在这里插入图片描述

    3.3 literal和length的压缩方式

    literal和length的压缩方式与distance类似。Literal是未匹配的字符,deflate是针对字节作为基本字符来编码的,所以literal的数值范围是0-255。Length表示重复字符串长度,length=1当然不会出现,因为一个字节不值得用distance+length来记录,deflate规定length最小值是3,必须3个以上字符的字符串出现重复才用distance+length记录。那么,最大的length是多少呢?理论上当然可以很长很长,比如一个文件就是连续的0,这个重复字符串长度其实接近于这个文件的实际长度。但是length的范围做了限制,限定length的个数跟literal一样,也只有256个,因为一个重复字符串达到了256个已经很长了,概率非常小。

    为什么要把literal和length二者合二为一呢?因为当解码器接收到一个比特流的时候,首先可以按照literal/length这个码表来解码,如果解出来是0-255,就表示未匹配字符,如果是256,那自然就结束,如果是257-285之间,则表示length,把后面扩展比特加上形成length后,后面的比特流肯定就表示distance,因此,实际上通过一个Huffman码表,对各类情况进行了统一,而不是通过加一个什么标志来区分到底是literal还是重复字符串。

    和distance一样, length(总共256个值)划分为29个区间,其结果如下图:
    在这里插入图片描述
    理解了上面的过程,就理解了ZIP压缩的第二步,第一步是LZ编码,第二步是对LZ编码后结果(literal、distance、length)进行的再编码,因为literal/length是一个码表,我们称其为Huffman码表1,distance那个码表称为Huffman码表2。前面我们已经分析了,Huffman码树用一个码字长度序列表示,称为CL(Code Length),记录两个码表的码字长度序列分别记为CL1、CL2。码树记录下来,对literal/length的编码比特流称为LIT比特流;对distance的编码比特流称为DIST比特流。

    按照上面的方法,LZ的编码结果就变成四块:CL1、CL2、LIT比特流、DIST比特流。CL1、CL2是码字长度的序列,这个序列就是一堆正整数,因此还可以继续对码表进行压缩。

    4. 对码表压缩

    对码表的压缩仍然沿用Huffman的想法,因为码表序列也是一堆整数,那么当然可以再次应用Huffman编码。不过在此之前,需要先对序列进行了一点处理。

    对于literal/length,总共有0-285这么多符号,前面章节已经说过,defalte算法构造的特殊huffman树可以使用码字长度序列来表示,所以这个序列长度为286,每个符号都有一个码字长度,当然,这里面可能会出现大段连续的0,因为某些字符或长度不存在,尤其是对英文文本编码的时候,非ASCII字符就根本不会出现,length较大的值出现概率也很小,所以出现大段的0是很正常的;对于distance也类似,也可能出现大段的0。因此先进行游程编码可以有效压缩数据。

    4.1 游程编码

    literal/length的编码符号总共286个(256个Literal+1个结束标志+29个length区间),distance的编码符号总共30个(30个区间),所以这颗码树不会特别深,Huffman编码后的码字长度不会特别长,最长不会超过15,也就是树的深度不会超过15(为什么)。因此,CL1和CL2这两个序列的任意整数值的范围是0-15。0表示某个整数没有出现(比如literal=0x12, length Code=8, distance Code=15等等)。

    什么叫游程呢?就是一段完全相同的数的序列。什么叫游程编码呢?说起来原理更简单,就是对一段连续相同的数,记录这个数一次,紧接着记录出现了多少个即可。比如CL序列如下:
    4, 4, 4, 4, 4, 3, 3, 3, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2

    那么,游程编码的结果为:
    4, 16, 01(二进制), 3, 3, 3, 6, 16, 11(二进制), 16, 00(二进制), 17,011(二进制), 2, 16, 00(二进制)

    这是什么意思呢?因为CL的范围是0-15,如果重复出现2次认为太短就不用游程编码,所以游程长度从3开始。用16这个特殊的数表示重复出现3、4、5、6个这样一个游程,分别由后面跟着的2bit数据00、01、10、11表示(实际存储的时候需要低比特优先存储,需要把比特倒序来存,博文的一些例子有时候会忽略这点,实际写程序的时候一定要注意,否则会得到错误结果)。于是4,4,4,4,4,这段游程记录为4,16,01,也就是说,4这个数,后面还会连续出现了4次。6,16,11,16,00表示6后面还连续跟着6个6,再跟着3个6;因为连续的0出现的可能很多,所以用17、18这两个特殊的数专门表示0游程,17后面跟着3个比特分别记录长度为3-10(总共8种可能)的游程;18后面跟着7个比特表示11-138(总共128种可能)的游程。17,011(二进制)表示连续出现6个0;18,0111110(二进制)表示连续出现62个0。总之记住,0-15是CL可能出现的值,16表示除了0以外的其它游程;17、18表示0游程。因为二进制实际上也是个整数,所以上面的序列用整数表示为:
    4, 16, 1, 3, 3, 3, 6, 16, 3, 16, 0, 17, 3, 2, 16, 0

    4.2 huffman压缩

    我们又看到了一串整数,这串整数的值的范围是0-18。这个序列称为SQ(Sequence的意思)。因为有两个CL1、CL2,所以对应的有两个SQ1、SQ2。

    针对SQ1、SQ2,deflate使用第三个Huffman码表来对这两个序列进行编码。通过统计各个整数(0-18范围内)的出现次数,按照相同的思路,对SQ1和SQ2进行了Huffman编码,得到的码流记为SQ1 bits和SQ2 bits。同时,这里又需要记录第三个码表,称为Huffman码表3。同理,这个码表也用相同的方法记录,也等效为一个码长序列,称为CCL,因为至多有0-18个,该树的深度至多为7,因此CCL的范围是0-7。

    当得到了CCL序列后,对这个序列用普通的3比特定长编码记录下来即可,即000代表0,111代表7。这个序列如果全部记录,那就需要19*3=57个比特, CL序列里面CL范围为0-15,特殊的几个值是16、17、18,如果把CCL序列位置置换一下,把16、17、18这些放前面,那么这个CCL序列就很可能最后面跟着一串0(因为CL=14,15这些很可能没有),所以最后还引入了一个置换,其示意图如下,分别表示置换前的CCL序列和置换后的CCL。可以看出,16、17、18对应的CCL被放到了前面,这样如果尾部出现了一些0,就只需要记录CCL长度即可,后面的0不记录。可以继续节省一些比特,不过这个例子尾部置换后只有1个0:
    在这里插入图片描述

    5. Deflate数据格式

    Deflate压缩数据时会先把数据分块再压缩,下面的deflate格式只针对其中一个数据块。其格式为:
    在这里插入图片描述

    • Header:3个比特,第一个比特BFINAL,如果是1,表示此部分为最后一个压缩数据块;否则表示这是deflate文件的某个中间压缩数据块,但后面还有其他数据块。这是ZIP中使用分块压缩的标志之一;

    • 第2、3比特表示3个选择:压缩数据中没有使用Huffman、使用静态Huffman、使用动态Huffman,这是对LZ77编码后的literal/length/distance进行进一步编码的标志。我们前面分析的都是动态Huffman,其实Deflate也支持静态Huffman编码,静态Huffman编码原理更为简单,无需记录码表(因为自己定义了一个固定的码表),但压缩率不高,所以大多数情况下都是动态Huffman。

    • HLIT:5比特,记录literal/length码树中码长序列(CL1)个数的一个变量。后面CL1个数等于HLIT+257(因为至少有0-255总共256个literal,还有一个256表示解码结束,但length的个数不定)。

    • HDIST:5比特,记录distance码树中码长序列(CL2)个数的一个变量。后面CL2个数等于HDIST+1。哪怕没有1个重复字符串,distance都为0也是一个CL。

    • HCLEN:4比特,记录Huffman码表3中码长序列(CCL)个数的一个变量。后面CCL个数等于HCLEN+4。PK认为CCL个数不会低于4个,即使对于整个文件只有1个字符的情况。

    • 接下来是3比特编码的CCL,一共HCLEN+4个,用以构造Huffman码表3;

    • 接下来是对CL1(码长)序列经过游程编码(SQ1:缩短的整数序列)后,并对SQ1继续用Huffman编码后的比特流。包含HLIT+257个CL1,其解码码表为Huffman码表3,用以构造Huffman码表1;

    • 接下来是对CL2(码长)序列经过游程编码(SQ2:缩短的整数序列)后,并对SQ2继续用Huffman编码后的比特流。包含HDIST+1个CL2,其解码码表为Huffman码表3,用于构造Huffman码表2;
      总之,上面的数据都是为了构造LZ解码需要的2个Huffman码表。
      接下来才是经过Huffman编码的压缩数据,解码码表为Huffman码表1和码表2。

    • 最后是数据块结束标志,即literal/length这个码表输入符号位256的编码比特。

    对倒数第1、2内容块进行解码时,首先利用Huffman码表1进行解码,如果解码所得整数位于0-255之间,表示literal未匹配字符,接下来仍然利用Huffman码表1解码;如果位于257-285之间,表示length匹配长度,之后需要利用Huffman码表2进行解码得到distance偏移距离;如果等于256,表示数据块解码结束。

    展开全文
  • deflate与gzip

    2018-11-08 21:39:20
    deflate与gzip

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow

    也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!

                   
    gzip是一种数据格式,默认且目前仅使用deflate算法压缩data部分;
    deflate是一种压缩算法,是huffman编码的一种加强。

    deflate与gzip解压的代码几乎相同,可以合成一块代码。
    区别仅有:

    deflate使用inflateInit(),而gzip使用inflateInit2()进行初始化,比 inflateInit()多一个参数: -MAX_WBITS,表示处理raw deflate数据。因为gzip数据中的zlib压缩数据块没有zlib header的两个字节。使用inflateInit2时要求zlib库忽略zlib header。在zlib手册中要求windowBits为8..15,但是实际上其它范围的数据有特殊作用,见zlib.h中的注释,如负数表示raw deflate。
    Apache的deflate变种可能也没有zlib header,需要添加假头后处理。即MS的错误deflate (raw deflate).zlib头第1字节一般是0x78, 第2字节与第一字节合起来的双字节应能被31整除,详见rfc1950。例如Firefox的zlib假头为0x7801,python zlib.compress()结果头部为0x789c。

    deflate 是最基础的算法,gzip 在 deflate 的 raw data 前增加了 10 个字节的 gzheader,尾部添加了 8 个字节的校验字节(可选 crc32 和 adler32) 和长度标识字节。
               

    给我老师的人工智能教程打call!http://blog.csdn.net/jiangjunshow

    这里写图片描述
    展开全文
  • deflate压缩

    千次阅读 2013-12-07 00:04:38
    deflate(RFC1951):一种压缩算法,使用LZ77和哈弗曼进行编码;  zlib(RFC1950):一种格式,是对deflate进行了简单的封装;  gzip(RFC1952):一种格式,也是对deflate进行的封装。  可以看出deflate是最核心的算法...
  • Deflate-gate-crx插件

    2021-04-04 18:00:08
    语言:English 唯一的deflate-gate扩展#缩小 压缩互联网上的所有足球!
  • 下面小编就为大家带来一篇JAVA中的deflate压缩实现方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
  • 易语言zlib deflate 解压缩源码
  • zip_deflate压缩易语言源码 天哥软件
  • An optimized data hiding scheme for Deflate codes
  • gzip和deflate

    2019-10-05 23:57:16
    gzip和deflate https://www.surfchen.org/archives/577 posted on 2013-04-06 05:13le...
  • deflate&gzip区别

    2020-08-04 10:09:05
    gzip是一种数据格式,默认且目前仅使用deflate算法压缩data部分;deflate是一种压缩算法,是huffman编码的一种加强。 deflate 是最基础的算法,gzip 在 deflate 的 raw data 前增加了 10 个字节的 gzheader,尾部...
  • zlib-Deflate压缩算法

    千次阅读 2019-05-31 18:26:48
    最近在做一些关于网络优化的一些事情,涉及到对纯数据(Data、字符串、Json等)进行压缩,用到了Deflate压缩算法,这里就简单说一下如何用OC实现 Deflate 先看代码 (后面会给出详细解析) Deflate.h // // ...
  • 主要介绍了C#实现页面GZip或Deflate压缩的方法,涉及C#通过GZipStream与DeflateStream实现页面压缩的相关技巧,需要的朋友可以参考下
  • DoS Deflate

    2014-07-03 09:57:51
    (D)DoS Deflate is a lightweight bash shell script designed to assist in the process of blocking a denial of service attack. It utilizes the command below to create a list of IP addresses connected t....
  • IE的deflate

    2018-04-16 10:24:01
    网上搜来的关键几句话:gzip与deflate区别 deflate使用inflateInit(),而gzip使用inflateInit2()进行初始化,比 inflateInit()多一个参数: -MAX_WBITS,表示处理raw deflate数据。因为gzip数据中的zlib压缩数据块...
  • Apache之deflate

    2017-03-12 23:58:53
    使用mod_deflate模块压缩页面优化传输速度 适用场景: (1) 节约带宽,额外消耗CPU;同时,可能有些较老浏览器不支持; (2) 压缩适于压缩的资源,例如文件文件; SetOutputFilter DEFLATE # mod_deflate ...
  • -D-DoS-Deflate 注意:我不再维护这个 fork,但是您可以找到 jgmdev 的一个 fork,其中包含对此脚本的许多修复和改进。 Zaf < > 的 (D)DoS deflate shell 脚本的分支 - 我将通过错误修复和其他改进来维护这个...
  • 本文主要向大家介绍了nodejs中关于gzip/deflate压缩的2种方法,分别是管道压缩和非管道压缩,十分详细,并附带示例,这里推荐给大家参考下。
  • 基于FPGA的Deflate算法核心模块设计.pdf
  • Deflate算法解读

    千次阅读 2018-06-11 14:56:16
    gzip 使用deflate算法进行压缩。通用类库为zlib,由LZ77+Huffman共同实现。1、 LZ77算法简介这一算法是由Jacob Ziv 和 Abraham Lempel 于 1977 年提出,所以命名为 LZ77,被一些人称为字典算法。2、 LZ77算法的压缩...
  • deflate及gzip格式说明

    2020-02-12 14:08:45
    前段时间公司的web服务器...本文就对gz文件格式作一个完整的描述,因为复杂的部分主要是deflate(rfc1951)格式包的实现,所以本文也可以作为 deflate格式的参考简要说明。 为了本文理解上的准确性和rfc1951的标准...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 76,279
精华内容 30,511
关键字:

deflate