2013-12-16 27 views
6

Mam pierwsze ciągłe 2/3 pliku, który został skompresowany za pomocą funkcji deflate() zlib. Ostatnia 1/3 została utracona podczas transmisji. Oryginalny nieskompresowany plik miał 600 KB.Jak nadymać częściowy plik zlib

Deflate został wywołany wiele razy przez nadajnik podczas krojenia oryginalnego pliku do rozmiarów kawałków 2KB i przekazywania Z_NO_FLUSH do końca pliku, gdy Z_FINISH został przekazany. Wynikowy kompletny skompresowany plik został przesłany, ale częściowo utracony zgodnie z opisem.

Czy można odzyskać część oryginalnego pliku? Jeśli tak, wszelkie sugestie dotyczące sposobu?

Używam zarówno implementacji zwykłego C ZLIB, jak i implementacji ZLIB w Pythonie 2.7.

Odpowiedz

10

Choć nie wiem, python, udało mi się uzyskać to do pracy:

#!/usr/bin/python 
import sys 
import zlib 
f = open(sys.argv[1], "rb") 
g = open(sys.argv[2], "wb") 
z = zlib.decompressobj() 
while True: 
    buf = z.unconsumed_tail 
    if buf == "": 
     buf = f.read(8192) 
     if buf == "": 
      break 
    got = z.decompress(buf) 
    if got == "": 
     break 
    g.write(got) 

To powinno wydobyć wszystko, co jest dostępne z częściowego pliku zlib.

+0

Dzięki, tak użyciu decompressobj() pracował. Używałem po prostu zlib.decompress() i podawałem błąd. Użycie dc_obj = zlib.decompressobj() i decomp_data_str = dc_obj.decompress (orig_data_str) rozwiązało problem. – JohnSantaFe

0

Następujące wydaje się być teoretycznie możliwe, ale wymaga majsterkowania z niskopoziomowymi procedurami zlib do pracy. W http://www.zlib.net/zlib_how.html znajdujemy Przykład programu zpipe.c i w linii według opisu linia:

porcja jest po prostu rozmiarem bufora do wprowadzania danych do ciągnięcia danych z procedury ZLib. Większe rozmiary buforów byłyby bardziej wydajne, szczególnie w przypadku nadmuchu(). Jeśli pamięć jest dostępna, należy użyć buforów o rozmiarze 128 KB lub 256 KB.

#define CHUNK 16384 
... 

Oto moja propozycja: ustawić bufor bardzo małe - jeśli jest obsługiwany, a może nawet do jednego bajta. W ten sposób rozpakujesz jak najwięcej, aż do nieuchronnego Z_BUF_ERROR. W tym momencie zwykle odrzuca się zebrane dane (poszukaj przedwczesnych połączeń telefonicznych, które "oczyszczają" za twoimi plecami), ale w twoim przypadku możesz po prostu przesłać strumień do pliku i zamknąć go, gdy znajdziesz, że nie możesz kontynuować.

Ostatnie kilka bajtów wyjścia może zawierać thrash, jeśli błędny symbol "ostateczny" został zdekodowany, lub zlib może przerwać przedwcześnie, zamiast wyprowadzać częściowy symbol. Ale wiesz, że twoje dane będą niekompletne tak czy inaczej, więc nie powinno to stanowić problemu.

2

Aktualizacja: jako @Mark Adler pointed out; częściowa zawartość może być rozpakowane pomocą zlib.decompressobj:

>>> decompressor = zlib.decompressobj() 
>>> decompressor.decompress(part) 
"let's compress some t" 

gdzie part jest zdefiniowany poniżej.

--- Old komentarz następująco:

Domyślnie zlib nie obsługuje częściowej zawartości w Pythonie.

to działa:

>>> compressed = "let's compress some text".encode('zip') 
>>> compressed 
'x\x9c\xcbI-Q/VH\xce\xcf-(J-.V(\xce\xcfMU(I\xad(\x01\x00pX\t%' 
>>> compressed.decode('zip') 
"let's compress some text" 

To nie działa, jeśli obciąć go:

>>> part = compressed[:3*len(compressed)/4] 
>>> part.decode('zip') 
Traceback (most recent call last): 
    File "<input>", line 1, in <module> 
    File ".../lib/python2.7/encodings/zlib_codec.py", lin 
e 43, in zlib_decode 
    output = zlib.decompress(input) 
error: Error -5 while decompressing data: incomplete or truncated stream 

To samo jeśli używamy zlib wyraźnie:

>>> import zlib 
>>> zlib.decompress(compressed) 
"let's compress some text" 
>>> zlib.decompress(part) 
Traceback (most recent call last): 
    File "<input>", line 1, in <module> 
error: Error -5 while decompressing data: incomplete or truncated stream