Wie dekomprimiere ich zlib-Daten unter UNIX?

106

Ich habe zlib-komprimierte Daten in Python wie folgt erstellt:

import zlib
s = '...'
z = zlib.compress(s)
with open('/tmp/data', 'w') as f:
    f.write(z)

(oder ein Liner in der Schale: echo -n '...' | python2 -c 'import sys,zlib; sys.stdout.write(zlib.compress(sys.stdin.read()))' > /tmp/data)

Jetzt möchte ich die Daten in der Shell dekomprimieren. Weder zcatnoch uncompressArbeit:

$ cat /tmp/data | gzip -d -
gzip: stdin: not in gzip format

$ zcat /tmp/data 
gzip: /tmp/data.gz: not in gzip format

$ cat /tmp/data | uncompress -
gzip: stdin: not in gzip format

Es scheint, dass ich eine gzip-ähnliche Datei erstellt habe, aber ohne Header. Leider sehe ich keine Möglichkeit, solche Rohdaten in der gzip-Manpage zu dekomprimieren, und das zlib-Paket enthält kein ausführbares Dienstprogramm.

Gibt es ein Dienstprogramm zum Dekomprimieren von ZLIB-Rohdaten?

Mykhal
quelle
Hier gibt es viele zusätzliche Antworten: stackoverflow.com/questions/3178566/deflate-command-line-tool
Jack O'Connor

Antworten:

140

Es ist auch möglich, es mit Standard- + zu dekomprimieren , wenn Sie nicht über oder andere Tools verfügen oder diese verwenden möchten .
Der Trick besteht darin, die magische gzip-Zahl und die Komprimierungsmethode vor die eigentlichen Daten von zlib.compress:

printf "\x1f\x8b\x08\x00\x00\x00\x00\x00" |cat - /tmp/data |gzip -dc >/tmp/out

Bearbeitungen:
@ d0sboots kommentiert: Für RAW-Deflate-Daten müssen Sie 2 weitere Nullbytes hinzufügen:
"\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x00"

Dieses Q on SO enthält weitere Informationen zu diesem Ansatz. Eine Antwort darauf deutet darauf hin, dass es auch eine 8-Byte-Fußzeile gibt.

Die Benutzer @ Vitali-Kushner und @ mark-bessey meldeten auch bei abgeschnittenen Dateien Erfolge, sodass eine GZIP-Fußzeile nicht unbedingt erforderlich zu sein scheint.

@ tobias-kienzler schlug diese funktion für den :
zlipd() (printf "\x1f\x8b\x08\x00\x00\x00\x00\x00" |cat - $@ |gzip -dc)

wkpark
quelle
gzip funktioniert nicht, aber zlib-flate (pdf-Seiteninhaltsstrom).
Daneel S. Yaitskov
69

User @tino hat unter der OpenSSL-Antwort einen Kommentar abgegeben, aber ich denke, das sollte separat sein:

zlib-flate -uncompress < FILE

Ich habe es versucht und es hat bei mir funktioniert.

zlib-flatekann im Paket gefunden werden qpdf(in Debian Squeeze und Fedora 23, laut Kommentaren in anderen Antworten)

Catskul
quelle
3
Im Gegensatz zu den anderen Antworten funktioniert dies unter OS X.
Polym 29.12.15
2
@polym, wie wurdest du auf macOS zlib-flate installiert ? Ich sehe es nirgendwo.
Wildcard
4
@Wildcard Entschuldigung für die verspätete Antwort. Ich denke, es kam mit dem qpdfPaket, das ich brewwie im Kommentar oben erwähnt installiert habe - oder schauen Sie sich den letzten Satz dieser Antwort an :). Auch qpdfist wirklich cool, haben so einen Blick auf sie zu , wenn Sie Zeit haben!
Polym
brau installiere qpdf, dann den oben aufgelisteten Befehl :-) danke!
Fernando Gabrieli
60

Ich habe eine Lösung gefunden (eine der möglichen), die openssl verwendet :

$ openssl zlib -d < /tmp/data

oder

$ openssl zlib -d -in /tmp/data

* HINWEIS: Die zlib-Funktionalität ist anscheinend in neueren openssl-Versionen> = 1.0.0 verfügbar (OpenSSL muss mit der Option zlib oder zlib-dynamic konfiguriert / erstellt werden, letztere ist Standard).

Mykhal
quelle
25
Auf Debian Squeeze (das OpenSSL 0.9.8 hat) gibt es zlib-flateim qpdfPaket. Es kann gerne verwendet werden zlib-flate -uncompress < FILE.
Tino
7
zlib wurde aus den neuesten Versionen von OpenSSL entfernt, daher ist dieser Tipp sehr hilfreich. @Tino
Alexandr Kurilin
1
Vielen Dank. Diese Lösung bietet eine bessere Erfahrung beim Dekomprimieren von kurzen Eingabedateien als die Antwort mit "gzip" ("openssl" dekomprimierte so viel wie möglich, während "gzip" das Drucken von "Unerwartetes Dateiende" abbrach).
Daniel K.
2
@Tino Dies sollte eine separate Antwort sein
Catskul
1
@Tino, es ist auch über das Paket qpdf auf Fedora 23 verfügbar. Alexandr Kurilin, zlib ist noch in 1.0.2d-fips verfügbar.
Maxschlepzig
28

Ich empfehle pigz von mark adler , mitautor der zlib compression library. Ausführen pigz, um die verfügbaren Flags anzuzeigen.

Du wirst bemerken:

-z --zlib Compress to zlib (.zz) instead of gzip format.

Sie können mit dem -dFlag dekomprimieren :

-d --decompress --uncompress Decompress the compressed input.

Angenommen, eine Datei mit dem Namen 'test':

  • pigz -z test - Erstellt eine zlib-komprimierte Datei mit dem Namen test.zz
  • pigz -d -z test.zz - konvertiert test.zz in die dekomprimierte Testdatei

Unter OSX können Sie ausführen brew install pigz

Snodnipper
quelle
7
Guter Fund! Es sieht so aus, als ob es zlib-Dateien von selbst erkennen kann, das unpigz test.zzwird auch funktionieren.
Stéphane Chazelas
habe meine Daten nicht dekomprimiert.
Cybernard
1
@cybernard vielleicht hast du keine zlib datei. überprüfen Sie mit:$>file hello.txt.zz hello.txt.zz: zlib compressed data
Snodnipper
11

zlibImplementiert die von gzip verwendete Komprimierung, jedoch nicht das Dateiformat. Verwenden Sie stattdessen das gzipModul , das selbst verwendet wird zlib.

import gzip
s = '...'
with gzip.open('/tmp/data', 'w') as f:
    f.write(s)
Jeremy Banks
quelle
ok, aber meine situation ist, dass ich zehntausende dieser
1
Also ... Ihre Dateien sind unvollständig. Möglicherweise müssen Sie sie mit zlibdekomprimieren und erneut mit komprimieren gzip, wenn Sie nicht über die ursprünglichen Daten verfügen.
Greg Hewgill
6
@mykhal, warum haben Sie zehntausende von Dateien erstellt, bevor Sie überprüft haben, ob Sie sie tatsächlich dekomprimieren können?
3
harpyon, ich kann sie dekomprimieren, ich frage mich nur, welche weniger oder häufigeren urility- oder zgip-einstellungen dafür verwendet werden können, wenn ich es nicht noch einmal in python machen
3

Das könnte es tun:

import glob
import zlib
import sys

for filename in sys.argv:
    with open(filename, 'rb') as compressed:
        with open(filename + '-decompressed', 'wb') as expanded:
            data = zlib.decompress(compressed.read())
            expanded.write(data)

Dann führe es so aus:

$ python expander.py data/*
Jeremy Banks
quelle
Danke, ich weiß über zlib.decompress. Wahrscheinlich würde ich eine Walk-Funktion verwenden. Ich bin nicht sicher, ob Shell meine große Menge an Dateien mit Glob Wildcard behandeln würde :)
Die von expand erstellte Datei wird für mich immer noch mit dem Shell- fileBefehl? Als "zlib-komprimierte Daten" ausgecheckt . Wie ist das?
K.-Michael Aye
Nö, funktioniert bei mir nicht einmal mit dem falschen Header.
Cybernard
3

Das zpipe.c hier von Mark Adler selbst gefundene Beispielprogramm (das mit der Quelldistribution der zlib-Bibliothek geliefert wird) ist für diese Szenarien mit rohen zlib-Daten sehr nützlich. Kompilieren Sie mit cc -o zpipe zpipe.c -lzund dekomprimieren: zpipe -d < raw.zlib > decompressed. Die Komprimierung kann auch ohne das -dFlag erfolgen.

Henno Brandsma
quelle
2

Unter macOS, einem vollständig POSIX-kompatiblen UNIX (formal zertifiziert!), OpenSSLGibt es keine zlibUnterstützung, zlib-flateund während die erste Lösung ebenso wie alle Python-Lösungen funktioniert, müssen sich die ZIP-Daten in einer Datei befinden und alle anderen Lösungen zwingen Sie, ein Python-Skript zu erstellen.

Hier ist eine Perl-basierte Lösung, die als einzeilige Befehlszeile verwendet werden kann, deren Eingabe über die STDIN-Pipe erfolgt und die mit einem frisch installierten MacOS sofort funktioniert:

cat file.compressed | perl -e 'use Compress::Raw::Zlib;my $d=new Compress::Raw::Zlib::Inflate();my $o;undef $/;$d->inflate(<>,$o);print $o;'

Schöner formatiert sieht das Perl-Skript so aus:

use Compress::Raw::Zlib;
my $decompressor = new Compress::Raw::Zlib::Inflate();
my $output;
undef $/;
$decompressor->inflate(<>, $output);
print $output;
Mecki
quelle
1

Sie können dies verwenden, um mit zlib zu komprimieren:

openssl enc -z -none -e < /file/to/deflate

Und dies zu entleeren:

openssl enc -z -none -d < /file/to/deflate
Danny R
quelle
4
Gibt unknown option '-z'auf Ubuntu 16.04 undOpenSSL 1.0.2g 1 Mar 2016
Tino
2
gleicher Fehler auf dem Mac
K.-Michael Aye
-3
zcat -f infile > outfile 

funktioniert bei mir auf fedora25

sigxcpu
quelle
1
zcatFunktioniert nur mit Dateien im gzip-Format.
Anthony Geoghegan