修复损坏的gzip压缩文件之原理篇

引言:UNIX/LINUX下大多数都是用gzip格式来做文件的压缩方案的,而gzip文件损坏的情况也屡见不鲜,常见的有遇到坏扇区、压缩进程io阻塞,或恢复后的压缩文件被破坏等。因近期有做关于gzip文件的修复研究,特分为三个篇章对此成果进行表述,分别为原理篇,方法篇,案例篇。此为第一部分原理篇。

gzip的压缩算法本质上是deflate(zip也几乎都用),这个算法其实是由LZ77算法加上一个变形的哈夫曼编码组成的。大概算法流程是:”原始数据--->LZ77--->哈夫曼 “这三个步骤。因啥夫曼树仍有可能进行压缩,所以,实质上的算法流程是:”原始数据--->LZ77--->(哈夫曼树->CL压缩) “

先来聊聊“原始数据--->LZ77”这一层的思想。LZ77的详细算法见相关文档,本文不做赘述,仅描述涉及本文主题的一些思想。本质上看,LZ77是基于对连续重复的字节片断用指向的方式表示来实现压缩。比如:有句英文叫business is business,为了简化这个句子(注意有空格),我们用business is (12,8)来表示,意思是括号内的数字并非原始数据,而是代表从当前位置向前12个字节,并且连续了8个字节的那段文字。这样一来,文字部分就变得简短了。当然,我们一定会注意到,对于每个句子,要额外有信息表示到底是原始数据,还是指针类的数据。所以,整个压缩后的数据,由三类不同的信息元素组成:本来就是这样的文字、指向的位置,指向的长度,这三个元素即是lz77算法中的literal、distance和length。

给定任何一段字节流,如果使用LZ77算法进行了压缩,就一定会得到一段由literal、distance和length组成的字节流,那要如何区分这三类元素呢?distance和length总是成对出现的,所以,其实是如何区分这2类:1、literal    2、distance与length。通过适当方法区分开这2类成员,就完成了LZ77算法的整个方法。

LZ77完成后,会形成一段较短的字节流。但这还不够,还要经过哈夫曼编码进行二次压缩才能使压缩比更为理想。

同样的原因,对哈夫曼编码原理不做过多解释,仅对涉及本文主题的一些原理进行概要性表述。关于哈夫曼编码,举个例子说明一下:如果有一段字节流(由字节为最小单位组成),这些字节流中每种字节值的出现概率是不相同的,但每个字节都使用了8位进行记录,从概率角度可以知道,这一定是可以再做优化的。哈夫曼就是针对这个思想的优化,简单地说,就如同生成了一个一一对应的映射字典,用一些短的位代替经常频繁出现的字节,用一些长的位代替不常出现的字节,这样,总体上就又进行了一次压缩。

当然,如何区分某个位置开始的是短的位还是些长的位呢?其实很简单,只要约定:短位用了的,比他长的就不再用这个短位做前缀即可。比如,如果英文中不想用空格间隔开单词了,只需要这样设计:I如果表示我的意思,那其他所有单词就不可能以I开头。AM如果表示”是”的含义,那既没有以A开头的单词,也没有以AM开头的更长的单词了。以此类推,或许Iamchinese就不用加空格也能间隔开了。

因为LZ77压缩后的数据元素中有literal、distance和length,为了有效区分,deflate算法把把literal和length合起来,使用一颗哈夫曼树。树中编码表述的数值如果小于255,即表示literal;如果等于256,表示本压缩块结束;如果大于256,表示length(需要减254得到);如果是length,再在其后紧跟distance的编码,distance使用单一的哈夫曼树,实现方法见相关文档。

literal、distance和length采用的哈夫曼树本身也是个大的负担,为了进一步压缩空间,deflate又对这两颗哈夫曼树进行了一次压缩,同样的,主体上,也是采用哈夫曼算法,这样,就是第三颗哈夫曼树了。

简单的结构如下图:

按照图中结构可知,一个gzip结构大致如下图所示:

可以看到,每个的压缩包均是独立存在的,包括其本身使用的动态哈夫曼树,也仅存在于其作用域的压缩包内。故而,只要找到每个压缩包的起始位置,如果这个包没被破坏,就可解出其对应内容。

通常而言,因gzip的压缩作业窗口仅32K,所以每个包的大小都不会很大,如果部分包损坏,只要找到下一个包的起始,即可正确解压后续的数据。

如果gzip压缩的是多个文件(并非tar之后再做gzip),此种情况则相对容易。对于gzip而言,文件内包含多个原始文件的,不可以多个文件共用一个压缩包,也就是说如果有一个文件损坏,并不影响其他文件。这种思路容易实现,也可以使用linux下的gzip recover来完成修复。

我们重点要讨论的如果单一文件(如TAR包)gzip后,若其中间损坏,如何正确解压出后面的数据。这个思路如果理解了,gzip recover的算法就非常容易理解了,其算法也似乎有些弱了。

详见下一篇章。

时间: 2024-10-05 09:35:00

修复损坏的gzip压缩文件之原理篇的相关文章

gzip压缩文件损坏修复原理和数据恢复方法

接修复损坏的gzip压缩文件之原理篇,再次引用GZIP结构图:已知修复一个损坏的gzip文件的关键环节在于找到下一个正常压缩包的起始点.根据结构图中的信息可知,每个压缩包的开始结构中有是否到达尾部标志.使用的哈夫曼树类型.以及3个哈夫曼树的树元素个数等.如果某个gzip文件中间有一个坏扇区,要找到坏扇区后的一个正常起点,仅需按位右移,一直移位到可以正常解压的某个位,就可能找到了正确的压缩包起始.而根据gzip文件的压缩作业窗口为32KB大小推算,这个遍历不会超过64KB即可找到.在内存中快速循环

修复损坏的gz或tar.gz压缩文件之方法篇

接修复损坏的gzip压缩文件之原理篇,再次引用GZIP结构图: 在上一篇中已知,修复一个损坏的gzip文件的关键环节在于找到下一个正常压缩包的起始点.根据结构图中的信息可知,每个压缩包的开始结构中有是否到达尾部标志.使用的哈夫曼树类型.以及3个哈夫曼树的树元素个数等.如果某个gzip文件中间有一个坏扇区,要找到坏扇区后的一个正常起点,仅需按位右移,一直移位到可以正常解压的某个位,就可能找到了正确的压缩包起始.而根据gzip文件的压缩作业窗口为32KB大小推算,这个遍历不会超过64KB即可找到.在

linux gzip(压缩文件或者目录)

减少文件大小有两个明显的好处,一是可以减少存储空间,二是通过网络传输文件时,可以减少传输的时间.gzip是在Linux系统中经常使用的一个对文件进行压缩和解压缩的命令,既方便又好用.gzip不仅可以用来压缩大的.较少使用的文件以节省磁盘空间,还可以和tar命令一起构成Linux操作系统中比较流行的压缩文件格式.据统计,gzip命令对文本文件有60%-70%的压缩率. 1.命令格式: gzip[参数][文件或者目录] 2.命令功能: gzip是个使用广泛的压缩程序,文件经它压缩过后,其名称后面会多

170814、Java使用gzip压缩文件、还原文件

package com.rick.utils; import java.io.*; import java.util.zip.GZIPInputStream; import java.util.zip.GZIPOutputStream; /******************************************************** *@Desc: gizp工具类 *@Author: ZRP *@Date: 2017/11/9 9:31 ********************

python gzip 压缩文件

压缩数据创建gzip文件 先看一个略麻烦的做法 ? 1 2 3 4 5 6 import StringIO,gzip content = 'Life is short.I use python' zbuf = StringIO.StringIO() zfile = gzip.GzipFile(mode='wb', compresslevel=9, fileobj=zbuf) zfile.write(content) zfile.close() 但其实有个快捷的封装,不用用到StringIO模块

linux 压缩文件的命令总结

Linux压缩文件的读取 ·    *.Z       compress 程序压缩的档案: ·    *.bz2     bzip2 程序压缩的档案: ·    *.gz      gzip 程序压缩的档案: ·    *.tar     tar 程序打包的数据,并没有压缩过: ·    *.tar.gz  tar 程序打包的档案,其中并且经过 gzip 的压缩! ·    *.zip     zip 程序压缩文件 ·    *.rar     rar 程序压缩文件 Compress压缩文件 [

实现在线压缩文件的实现程序代码

[引入using System.Diagnostics;using Microsoft.Win32;] #region 使用GZip压缩文件,返回bool值 /// <param name="FileSource">要压缩的源文件名</param> /// <param name="FileTarget">压缩后的文件名</param> /// <returns>压缩后的成功类型</returns&g

Linux 压缩文件的命令行总结

Linux压缩文件的读取 ·    *.Z       compress 程序压缩的档案: ·    *.bz2     bzip2 程序压缩的档案: ·    *.gz      gzip 程序压缩的档案: ·    *.tar     tar 程序打包的数据,并没有压缩过: ·    *.tar.gz  tar 程序打包的档案,其中并且经过 gzip 的压缩! ·    *.zip     zip 程序压缩文件 ·    *.rar     rar 程序压缩文件 Compress压缩文件 [

.tar.xz压缩文件的解压

xz是一种压缩文件格式,采用LZMA SDK压缩,目标文件较gzip压缩文件(.gz或·tgz)小30%,较·bz2小15%. Linux内核和python源代码都有采用这种压缩方式,那么如何对其进行解压呢? 如今tar命令已经可以完成解压,可以使用 tar -xJvf linux-4.1.2.tar.xz 单行命令一次完成解压. 也可以先使用xz -d linux-4.1.2.tar.xz将其解压为tar文件,然后在使用tar -xvf linux-4.1.2.tar命令完成解压.各种Linu