2016-11-17 84 views
1

我正在嘗試編寫/讀取MS-ZIP壓縮CAB文件的代碼。 MS-ZIP使用zlib中實現的相同放氣算法。我已經簡化了這個簡單的腳本,只涉及zlib。zlib:解壓縮數據時出錯-3:無效距離太遠

  • 我知道壓縮功能是正確的,因爲其他CAB提取工具可以讀取文件產生這樣。

  • 解壓縮功能不起作用。當需要解壓縮多個塊時,它會失敗。

我無法獲得與壓縮代碼相匹配的解壓縮代碼。

import sys, struct, zlib 

MAX_CHUNK_SIZE = 100 

def main(): 
    uncomp = (b'[email protected][email protected][email protected]@<GJHE=EGE<[email protected]?<IABT>EK' 
       b'<[email protected]?DGDS>[email protected]' 
       b'[email protected]=IGG<?JQBGBPLOPONU?IBBSNBK<[email protected]>H=CQ?BS><@UE' 
       b'[email protected]>?JOSEQRCTP>S<?N>[email protected]??ARJ>QUJSHLQN<P<>D==') 

    print("python", sys.version) 
    print("zlib version", zlib.ZLIB_VERSION) 
    print("zlib runtime version", zlib.ZLIB_RUNTIME_VERSION) 

    chunks = compress(uncomp) 
    decomp = decompress(chunks) 
    assert(uncomp == decomp) 


def compress(data): 
    start_off = 0 
    data_size = len(data) 
    remaining = data_size 
    res = [] 
    zdict = b'' 

    while start_off < data_size: 
     print("compress chunk %d"%len(res)) 

     chunk_size = min(MAX_CHUNK_SIZE, remaining) 
     chunk = data[start_off:start_off+chunk_size] 
     c = b'' 

     z = zlib.compressobj(wbits=-15, zdict=zdict) 
     c += z.compress(chunk) 
     c += z.flush(zlib.Z_FINISH) 

     res.append(c) 

     zdict = chunk 
     start_off += chunk_size 
     remaining -= chunk_size 

    return res 

def decompress(chunks): 
    zdict = b'' 
    res = [] 

    for i, c in enumerate(chunks): 
     print("decompress chunk %d"%i) 
     out = b'' 

     z = zlib.decompressobj(wbits=-15, zdict=zdict) 
     out += z.decompress(c) 
     out += z.flush() 
     zdict = out 

     res.append(out) 

    return b''.join(res) 


if __name__ == '__main__': 
    main() 

當我運行該腳本,我得到:

python 3.4.5 (default, Jul 03 2016, 13:55:08) [GCC] 
zlib version 1.2.8 
zlib runtime version 1.2.8 
compress chunk 0 
compress chunk 1 
decompress chunk 0 
decompress chunk 1 
Traceback (most recent call last): 
    File "bug.py", line 65, in <module> 
    main() 
    File "bug.py", line 16, in main 
    decomp = decompress(chunks) 
    File "bug.py", line 55, in decompress 
    out += z.decompress(c) 
zlib.error: Error -3 while decompressing data: invalid distance too far back 

它也不能對ideone.com http://ideone.com/baD3gg這是運行蟒蛇3.4.3+的zlib 1.2.8

+0

我剛剛複製並粘貼你的代碼,運行它,並得到'結果12/12確定'。 –

+1

(哇,嗨馬克!!)我一直得到這些錯誤(測試5,6,7,8,9,10,11有時2,3)。運行zlib 1.2.8。 我試圖轉儲數據並用C程序解壓縮,與python腳本(也鏈接到1.2.8)相同的結果將用更多的代碼編輯我的文章。 – knarf

+0

我已編輯帖子。 – knarf

回答

1

看來我是遇到CPython問題#27164。正如我在寫這篇文章(2016年11月21日)時,修正版僅適用於分支機構主和3.5版。

https://bugs.python.org/issue27164

+0

的確,我的python版本是3.5.2。我得到:'python 3.5.2(v3.5.2:4def2a2901a5,Jun 26 2016,10:47:25) [GCC 4.2.1(Apple Inc. build 5666)(dot 3)] zlib 1.2.3版本 zlib運行時版本1.2.8 壓縮數據塊0 壓縮數據塊1 解壓縮數據塊0 解壓縮數據塊1' –