2016-11-17 2 views
1

Я пытаюсь написать код для записи/чтения сжатых CAB-файлов MS-ZIP. MS-ZIP использует тот же алгоритм дефляции, реализованный в zlib. Я упростил проблему для этого простого скрипта, который включает только zlib.zlib: Ошибка -3 при распаковке данных: неверное расстояние слишком далеко назад

  • Я знаю, что функция сжатия правильная, поскольку другие инструменты для извлечения CAB могут читать файлы, создающие этот способ.

  • Функция декомпрессии не работает. Он терпит неудачу, когда необходимо декомпрессировать более 1 фрагмента.

Я не могу получить код декомпрессии, соответствующий коду сжатия.

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 OK'. –

+1

(ничего себе, привет Марк !!) Я последовательно получаю эти ошибки (тесты 5,6,7,8,9,10,11 раз 2, 3). Запуск zlib 1.2.8. Я попытался сбрасывать данные и распаковывать их с помощью программы на С, те же результаты, что и скрипт python (также связанный с 1.2.8), будут редактировать мой пост с большим количеством кода. – knarf

+0

Я отредактировал сообщение. – knarf

ответ

1

Кажется, я был запущен в проблему CPython # 27164. Поскольку я пишу это (2016-11-21), исправление доступно только в master-серверах и только для 3.5.

https://bugs.python.org/issue27164

+0

Действительно версия python у меня есть 3.5.2. Я получил: 'python 3.5.2 (v3.5.2: 4def2a2901a5, 26 июня 2016, 10:47:25) [GCC 4.2.1 (Apple Inc. build 5666) (точка 3)] zlib версия 1.2.3 zlib версия исполнения 1.2.8 компрессионный кусок 0 компрессионный блок 1 распаковать кусок 0 распаковать кусок 1' –

Смежные вопросы