gzip壓縮檔案損壞修復原理和資料恢復方法

2021-09-27 05:39:11 字數 2044 閱讀 7061

接修復損壞的gzip壓縮檔案之原理篇,再次引用gzip結構圖:

已知修復乙個損壞的gzip檔案的關鍵環節在於找到下乙個正常壓縮包的起始點。根據結構圖中的資訊可知,每個壓縮包的開始結構中有是否到達尾部標誌、使用的哈夫曼樹型別、以及3個哈夫曼樹的樹元素個數等。如果某個gzip檔案中間有乙個壞扇區,要找到壞扇區後的乙個正常起點,僅需按位右移,一直移位到可以正常解壓的某個位,就可能找到了正確的壓縮包起始。而根據gzip檔案的壓縮作業視窗為32kb大小推算,這個遍歷不會超過64kb即可找到。在記憶體中快速迴圈可以很快找到,但需要有明確的判斷錯誤的方法。

首先可以明確的是結尾標誌,應該為0(我們是從損壞的點向後查)。而哈夫曼樹型別也大致應該是動態哈夫曼(0x02),cl1的元素個數應該取值為257到286之間(包含邊界),cl2的元素個數應小於等於30,ccl的元素個數取值可為1-15(包含邊界)。

其實,還可以參考的東西有,解開的哈夫曼樹是否異常,或者通過規律性原則找到最後乙個取值為256的值,但這些演算法應該是較為麻煩的,有上面的演算法連續校驗幾個壓縮塊就足夠了。

具體方法是對gzip的原始碼做修改,進行遍歷。因時間關係,未做成通用工程,僅快速修改了部分**。大致的修改點為:

在unzip.c中,

error("invalid compressed data--format violated");

這一行前,獲取當前解碼位元組位置即可。

1、inflate.c檔案中,改

if (nl > 286 || nd > 30)

#endif

return 1;

為:

if (nl > 286 || nd > 30||nl <257 || nd <1)

#endif

return 1;

2、inflate.c檔案中,在int inflate_block(e)函式中

在如下**前

bb = b; 

bk = k;

加入**:

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

return 2;

3、inflate.c檔案中,在int inflate_block(e)函式尾部

把if (t == 0) 與if (t == 1)的情況都直接返回錯誤值2。

4、inflate.c檔案中,函式int inflate()中,改

if ((r = inflate_block(&e)) != 0) 

return r; 

end

為:

unsigned t;           /* block type */ 

register ulg b;       /* bit buffer */ 

register unsigned k;  /* number of bits in bit buffer */ 

while (inptr <= insize) 

else 

}

此4步完成後,試著除錯這個錯誤的.gz檔案,當然,也可以在**中解釋完頭部結構後加乙個seek,直接seek到損壞位置。

通常情況下,輸出printf(「get by www.datahf.net!」)這行**時,已經找到了正確的起始位。

找到起始位後,也可以構造或拷貝乙個正常的gzip檔案頭,再拼接好找到的位流,即可解壓了。(如果位流不是位元組對齊的,可能要全部做位移)。拼接後很多壓縮檔案就可以開啟甚至於解壓了,不過,有可能會報錯,主要是尾部的校驗和大小錯,其實可以忽略。

如果拼接好了linux下,不能直接用「gzip –d」解壓,因其crc有錯誤,會導致解壓到99%後報錯,然後把檔案刪除,換成管道命令即可:

修復損壞的gzip壓縮檔案原理和修復方法

引用一下gzip的底層結構圖如下 已知修復乙個損壞的gzip檔案的關鍵環節在於找到下乙個正常壓縮包的起始點。根據結構圖中的資訊可知,每個壓縮包的開始結構中有是否到達尾部標誌 使用的哈夫曼樹型別 以及3個哈夫曼樹的樹元素個數等。如果某個gzip檔案中間有乙個壞扇區,要找到壞扇區後的乙個正常起點,僅需按...

gzip壓縮檔案 解壓檔案

解壓gzip壓縮格式檔案 eg 123.mms param source 原始檔 param target 目標檔案 public static void ungzipfile file source,string target throws exception gzin.close 關閉壓縮輸入流...

tar解壓和壓縮檔案詳解

希臘1 10 i ii iii iv v vi vii viii ix x 使用tar壓縮檔案 i.tar zcvf test.tar.gz test 該命令表示壓縮當前資料夾下的資料夾test,壓縮字尾名為test.tar.gz ii.如果不需要壓縮成gz,只需要字尾為tar格式的,那麼輸入如下命...