2013-12-16 9 views
6

Ich habe die ersten zusammenhängenden 2/3 einer Datei, die mit zlib deflate() -Funktion komprimiert wurde. Das letzte 1/3 wurde in der Übertragung verloren. Die ursprüngliche unkomprimierte Datei war 600 KB.Wie man eine partielle ZLIB-Datei aufblähen

Deflate wurde mehrmals vom Sender aufgerufen, während die ursprüngliche Datei in Chunk-Größen von 2KB zerhackt wurde und Z_NO_FLUSH bis zum Ende der Datei übergeben wurde, wenn Z_FINISH übergeben wurde. Die resultierende vollständige komprimierte Datei wurde übertragen, ging jedoch teilweise wie beschrieben verloren.

Ist es möglich, einen Teil der ursprünglichen Datei wiederherzustellen? Wenn ja, irgendwelche Vorschläge wie?

Ich verwende sowohl die einfache C-Implementierung von ZLIB, und/oder die Python 2.7-Implementierung von ZLIB.

Antwort

10

Obwohl ich weiß, Python nicht, konnte ich diese Arbeit bekommen:

#!/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) 

dass extrahieren sollte alles, was aus dem Teil-zlib-Datei verfügbar ist.

+0

Danke, ja mit decompressobj() hat funktioniert. Ich benutzte einfach zlib.decompress() und es gab einen Fehler. Mit dc_obj = zlib.decompressobj() und decomp_data_str = dc_obj.decompress (orig_data_str) wurde das Problem gelöst. – JohnSantaFe

0

Die folgenden scheint machbar in der Theorie, aber muss basteln mit Low-Level-zlib-Routinen zu arbeiten. In http://www.zlib.net/zlib_how.html finden wir ein Beispielprogramm zpipe.c, und in seiner Zeile für Zeile Beschreibung:

CHUNK ist einfach die Puffergröße für Daten und ziehen Daten aus den zlib-Routinen Fütterung. Größere Puffergrößen wären effizienter, insbesondere für das Aufblasen(). Wenn der Speicher verfügbar ist, sollten Puffergrößen in der Größenordnung von 128 K oder 256 KB verwendet werden.

#define CHUNK 16384 
... 

Hier ist mein Vorschlag: Sie setzen die Puffer sehr klein - falls unterstützt, vielleicht sogar auf ein Byte. Auf diese Weise werden Sie so viel wie möglich dekomprimieren bis zum unvermeidlichen Z_BUF_ERROR. An diesem Punkt werden die gesammelten Daten normalerweise verworfen (suchen Sie nach vorzeitigen deflate_end Aufrufen, die hinter Ihrem Rücken "aufräumen"), aber in Ihrem Fall könnten Sie einfach in eine Datei streamen und sie schließen, wenn Sie feststellen, dass Sie nicht weitermachen können.

Die letzten paar Bytes der Ausgabe können Thrash enthalten, wenn das falsche "final" -Symbol dekodiert wurde, oder zlib kann vorzeitig abbrechen, anstatt ein Teilsymbol auszugeben. Aber Sie wissen, dass Ihre Daten unvollständig sind sowieso, so sollte das kein Problem sein.

2

Update: wie @Mark Adler pointed out; Teilinhalt kann zlib.decompressobj dekomprimiert werden, unter Verwendung von:

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

wo part unten definiert ist.

--- Alter Kommentar folgt:

standardmäßig zlib nicht Teil-Inhalt in Python nicht handhaben.

Dies funktioniert:

>>> 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" 

Es funktioniert nicht, wenn wir sie gestutzt:

>>> 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 

Das gleiche, wenn wir zlib explizit verwenden:

>>> 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