2013-03-29 67 views
1

我有一個由壓縮的內容和一個32字節的頭組成的文件。標題包含時間戳,壓縮大小和未壓縮大小等信息。如何強制zlib解壓超過X字節?

該文件本身約爲490mb,標題表示未壓縮的大小接近2.7gb(顯然不正確,因爲它也認爲壓縮大小爲752mb)。

我已經剝離了標題並生成了壓縮的有效內容,並且可以使用zlib對其進行解壓縮。

問題是,它只是解壓縮19kb,這比490mb小得多(應該是最低限度,但我預計大約700mb未壓縮)。

我的代碼如下:

import zlib 

def consume (inputFile): 
    content = inputFile.read() 
    print "Attempting to process " + str(len(content)) + " bytes..." 
    outfile = open('output.xml', 'w') 
    inputFile = zlib.decompress(content) 
    print "Attempting to write " + str(len(inputFile)) + " bytes..." 
    outfile.write(inputFile) 
    outfile.close() 

infile = open('payload', 'rb') 

consume(infile) 

infile.close() 

運行時,該程序的輸出:

嘗試處理489987232個字節... 試圖寫入18602個字節...

我試過使用zlib.decompressionobj(),雖然這會產生不正確的標題警告。 zlib.decompress()工作正常,併產生我期望的解壓縮XML ......只是太少了。

任何指標或建議,非常感謝!

+0

該文件來自哪裏?您是否可以重新下載它,回滾到以前的版本,從備份恢復等? – abarnert

+0

由於內容的描述不同,Th文件肯定聽起來很腐敗。 – nneonneo

+0

@abarnert該文件由合作公司提供(在Dropbox上)。我可以試着找到另一個並放棄它。感謝指針 - 我一直假設我的代碼或方法是不正確的,但如果它證明是一個重大緩解的文件! – jscarto

回答

3

您顯然有一個損壞的文件。

您將無法強制zlib忽略這種腐敗 - 如果您確實這樣做,您很可能會得到700MB垃圾或一些隨機數量的垃圾,或者......這取決於什麼腐敗是在哪裏。但是你有可能獲得任何有用的機會都很渺茫。

zlib的塊不是隨機訪問的,或分隔的,甚至是字節對齊的;除非您能夠處理之前的區塊,否則很難分辨您何時到達下一個區塊。

此外,樹木從一個塊到另一個塊都在增長,所以即使你可以跳到下一個塊,你的樹也會出錯,除非你非常幸運並且不需要垃圾,否則你會解壓垃圾。樹的破碎部分。更糟糕的是,任何塊都可以重新啓動樹(或者甚至切換壓縮器)。如果你錯過,即使你得到非常幸運,你正在解壓縮垃圾。這不僅僅是「跳過這個字符串,因爲我不認識它」,如果你不認識,你甚至不知道字符串有多少位,所以你不能跳過它。這使我們回到第一點 - 甚至不能跳過單個字符串,更不用說整個字符串。

要更好地理解這一點,請參閱RFC 1951,其中描述了zlib所使用的格式。嘗試通過一些簡單的示例(第一個塊中的幾個字符串,第二個塊中的幾個新字符串)手動工作,以便以難以撤消的方式來破壞它們是多麼容易(除非您確切地知道它們是如何被損壞)。這不是不可能(畢竟,破解加密的郵件並非不可能),但我不相信它可以完全自動化,而且這不是你可能爲了好玩而做的事。

如果你有重要的數據(並且不能重新下載它,回滾到以前的版本,從備份恢復等),一些數據恢復服務聲稱能夠恢復損壞的zlib/gz/zip文件。我猜這個花費了一個手臂和一條腿,但它可能是正確數據的正確答案。

當然,我可能錯了,這不是可自動化的。那裏有一些zip恢復工具。據我所知,所有他們可以做的zlib流是跳過該文件,並恢復其他文件...但也許其中一些有一些技巧,在某些情況下破流工作。

+0

這非常有道理 - 感謝您的詳細回覆和鏈接!數據作爲測試用例提供給我們,所以應該可以重新獲取並重試(保持我的手指交叉!)。 – jscarto

+0

經過一段時間的休息後,我發現了這個問題。事實證明,數據沒有被破壞。相反,壓縮文件由多個級聯流組成。因此,我一次解壓縮對象的嘗試只讀取第一個流,產生小小的19kb結果。 我已經調整了我的代碼來解決這個問題,但我現在遇到了一個新問題 - 解壓縮[glacially slow](http://stackoverflow.com/questions/16506590/python-and-zlib -terribly-緩慢減壓,級聯流)。 – jscarto

0

您需要檢查zlib.error,看看它爲什麼停止。爲什麼停止?