gzip壓縮文件損壞修復原理和數據恢復方法

接修復損壞的gzip壓縮文件之原理篇,再次引用GZIP結構圖:
gzip壓縮文件損壞修復原理和數據恢復方法
已知修復一個損壞的gzip文件的關鍵環節在於找到下一個正常壓縮包的起始點。根據結構圖中的信息可知,每一個壓縮包的開始結構中有是否到達尾部標誌、使用的哈夫曼樹類型、以及3個哈夫曼樹的樹元素個數等。若是某個gzip文件中間有一個壞扇區,要找到壞扇區後的一個正常起點,僅需按位右移,一直移位到能夠正常解壓的某個位,就可能找到了正確的壓縮包起始。而根據gzip文件的壓縮做業窗口爲32KB大小推算,這個遍歷不會超過64KB便可找到。在內存中快速循環能夠很快找到,但須要有明確的判斷錯誤的方法。
首先能夠明確的是結尾標誌,應該爲0(咱們是從損壞的點向後查)。而哈夫曼樹類型也大體應該是動態哈夫曼(0x02),cl1的元素個數應該取值爲257到286之間(包含邊界),cl2的元素個數應小於等於30,ccl的元素個數取值可爲1-15(包含邊界)。
其實,還能夠參考的東西有,解開的哈夫曼樹是否異常,或者經過規律性原則找到最後一個取值爲256的值,但這些算法應該是較爲麻煩的,有上面的算法連續校驗幾個壓縮塊就足夠了。
具體方法是對gzip的源碼作修改,進行遍歷。因時間關係,未作成通用工程,僅快速修改了部分代碼。大體的修改點爲:linux

一,找到損壞點:

在unzip.c中,
error("invalid compressed data--format violated");
這一行前,獲取當前解碼字節位置便可。
 算法

2、遍歷找到損壞點:

一、inflate.c文件中,改ide

if (nl > 286 || nd > 30)
#endif
return 1;

爲:函數

if (nl > 286 || nd > 30||nl <257 || nd <1)
#endif
return 1;

二、inflate.c文件中,在int inflate_block(e)函數中
在以下代碼前.net

bb = b; 
bk = k;

加入代碼:3d

if ((t != 2) || (*e != 0)) 
return 2;

三、inflate.c文件中,在int inflate_block(e)函數尾部
把if (t == 0) 與if (t == 1)的狀況都直接返回錯誤值2。
 
四、inflate.c文件中,函數int inflate()中,改調試

if ((r = inflate_block(&e)) != 0) 
return r; 
end

爲:code

unsigned t;           /* block type */ 
register ulg b;       /* bit buffer */ 
register unsigned k;  /* number of bits in bit buffer */ 
while (inptr <= insize) 
{ 
    unsigned int tptr = inptr; 
    unsigned int tbk = bk; 
    unsigned long tbb = bb; 
    unsigned int twp = wp; 
    long long tstart = *(long long*)(inbuf + tptr); 
    if ((r = inflate_block(&e)) != 0) 
    { 
        inptr = tptr; 
        bb = tbb; 
        bk = tbk; 
        wp = twp; 
        b = bb; 
        k = bk; 
        NEEDBITS(1) 
        DUMPBITS(1) 
    } 
    else 
    { 
        printf("get by www.datahf.net!"); //也可輸出tstart,bb,bk 值,轉載時請保留版權信息:www.datahf.net張宇 
    } 
} 

此4步完成後,試着調試這個錯誤的.gz文件,固然,也能夠在代碼中解釋完頭部結構後加一個seek,直接seek到損壞位置。
一般狀況下,輸出printf(「get by www.datahf.net!」)這行代碼時,已經找到了正確的起始位。
找到起始位後,也能夠構造或拷貝一個正常的gzip文件頭,再拼接好找到的位流,便可解壓了。(若是位流不是字節對齊的,可能要所有作位移)。拼接後不少壓縮文件就能夠打開甚至於解壓了,不過,有可能會報錯,主要是尾部的校驗和大小錯,其實能夠忽略。
若是拼接好了linux下,不能直接用「gzip –d」解壓,因其crc有錯誤,會致使解壓到99%後報錯,而後把文件刪除,換成管道命令便可:orm

相關文章
相關標籤/搜索