Come decomprimere i dati zlib in UNIX?


107

Ho creato i dati compressi con zlib in Python, in questo modo:

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

(o uno-liner in guscio: echo -n '...' | python2 -c 'import sys,zlib; sys.stdout.write(zlib.compress(sys.stdin.read()))' > /tmp/data)

Ora voglio decomprimere i dati nella shell. Né zcatuncompresslavoro:

$ 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

Sembra che abbia creato un file simile a gzip, ma senza intestazioni. Sfortunatamente non vedo alcuna opzione per decomprimere tali dati grezzi nella pagina man di gzip e il pacchetto zlib non contiene alcuna utilità eseguibile.

Esiste un'utilità per decomprimere i dati zlib grezzi?


Risposte:


141

È anche possibile decomprimerlo usando standard + , se non si dispone o si desidera utilizzare o altri strumenti.
Il trucco è anteporre il numero magico di gzip e il metodo di compressione ai dati effettivi da zlib.compress:

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

Modifiche:
@ d0sboot commentati: per i dati RAW Deflate, è necessario aggiungere altri 2 byte null:
"\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x00"

Questa Q su SO fornisce ulteriori informazioni su questo approccio. Una risposta suggerisce che esiste anche un piè di pagina da 8 byte.

Gli utenti @ Vitali-Kushner e @ mark-bessey hanno riportato il successo anche con file troncati, quindi un footer gzip non sembra strettamente necessario.

@ tobias-kienzler ha suggerito questa funzione per il :
zlipd() (printf "\x1f\x8b\x08\x00\x00\x00\x00\x00" |cat - $@ |gzip -dc)


gzip non funziona, ma zlib-flate funziona (flusso di contenuti della pagina pdf).
Daneel S. Yaitskov,

70

L'utente @tino ha commentato sotto la risposta OpenSSL ma penso che questo dovrebbe essere separato:

zlib-flate -uncompress < FILE

Ho provato questo e ha funzionato per me.

zlib-flatepuò essere trovato nel pacchetto qpdf(in Debian Squeeze e Fedora 23, secondo i commenti in altre risposte)


3
Contrariamente alle altre risposte, questa funziona su OS X.
polimero

2
@polym, come sei stato zlib-flate installato su macOS? Non lo vedo da nessuna parte.
Carattere jolly

4
@Wildcard scusa per la risposta in ritardo. Penso che sia arrivato con il qpdfpacchetto che ho installato brewcome menzionato nel commento sopra - o guarda l'ultima frase di questa risposta :). Inoltre, qpdfè davvero bello, quindi dai un'occhiata anche se hai tempo!
polimero

brew install qpdf, quindi il comando sopra elencato :-) grazie!
Fernando Gabrieli,

60

Ho trovato una soluzione (una delle possibili), sta usando openssl :

$ openssl zlib -d < /tmp/data

o

$ openssl zlib -d -in /tmp/data

* NOTA: la funzionalità zlib è apparentemente disponibile nelle recenti versioni di openssl> = 1.0.0 (OpenSSL deve essere configurato / costruito con l'opzione zlib o zlib-dynamic, quest'ultima è predefinita)


25
Su Debian Squeeze (che ha OpenSSL 0.9.8) c'è zlib-flatenel qpdfpacchetto. Può essere usato come zlib-flate -uncompress < FILE.
Tino,

7
zlib è stato rimosso dalle ultime versioni di OpenSSL, quindi questo suggerimento è molto utile @Tino
Alexandr Kurilin,

1
Grazie. Questa soluzione offre un'esperienza migliore nella decompressione di file di input brevi rispetto alla risposta utilizzando "gzip" ("openssl" si è decompresso il più possibile mentre "gzip" ha interrotto la stampa "fine del file inattesa").
Daniel K.

2
@Tino questa dovrebbe essere una risposta separata
Catskul

1
@Tino, è anche disponibile tramite il pacchetto qpdf su Fedora 23. Alexandr Kurilin, zlib è ancora disponibile in 1.0.2d-fips.
maxschlepzig,

28

Consiglio Pigz di Mark Adler , coautore della libreria di compressione zlib. Eseguire pigzper vedere i flag disponibili.

Noterai:

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

Puoi decomprimere usando il -dflag:

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

Supponendo un file chiamato 'test':

  • pigz -z test - crea un file compresso zlib chiamato test.zz
  • pigz -d -z test.zz - converte test.zz nel file di test decompresso

Su OSX è possibile eseguire brew install pigz


7
Buona scoperta! Sembra che sia in grado di rilevare i file zlib da solo, quindi unpigz test.zzfunzionerà anche.
Stéphane Chazelas,

non ha decompresso i miei dati.
cybernard,

1
@cybernard forse non hai un file zlib. verificare con:$>file hello.txt.zz hello.txt.zz: zlib compressed data
snodnipper

11

zlibimplementa la compressione utilizzata da gzip, ma non il formato del file. Invece, dovresti usare il gzipmodulo , che a sua volta usa zlib.

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

ok, ma la mia situazione è che ho creato decine / centinaia di migliaia di quei file, quindi .. :)

1
quindi ... i tuoi file sono incompleti. Forse dovrai decomprimerli zlibe ricomprimerli con gzip, se non hai ancora i dati originali.
Greg Hewgill,

6
@mykhal, perché hai creato diecimila / centinaia di file prima di verificare che potresti effettivamente decomprimerli?

3
harpyon, posso decomprimerli, mi chiedo solo quali impostazioni di urilità o zgip più o meno comuni possono essere usate per questo, se non voglio farlo di nuovo in Python

3

Questo potrebbe farlo:

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)

Quindi eseguilo in questo modo:

$ python expander.py data/*

grazie, lo so zlib.decompress. probabilmente userei qualche funzione di camminata. non sono sicuro se la shell gestirà la mia enorme quantità di file con il carattere jolly glob :)

Il file creato da Espanso continua a essere verificato come "dati compressi zlib" per me, utilizzando il filecomando shell ? Come va?
K.-Michael Aye,

no non funziona per me nemmeno con l'intestazione falsa.
cybernard,

3

Il programma di esempio zpipe.c trovato qui dallo stesso Mark Adler (viene fornito con la distribuzione di origine della libreria zlib) è molto utile per questi scenari con dati zlib non elaborati. Compilare con cc -o zpipe zpipe.c -lze per decomprimere: zpipe -d < raw.zlib > decompressed. Può anche fare la compressione senza la -dbandiera.


2

Su macOS, che è un UNIX completamente conforme a POSIX (formalmente certificato!), OpenSSLNon ha zlibsupporto, non esiste zlib-flateneanche e mentre la prima soluzione funziona così come tutte le soluzioni Python, la prima soluzione richiede che i dati ZIP siano in un file e tutte le altre soluzioni ti costringono a creare uno script Python.

Ecco una soluzione basata su Perl che può essere utilizzata come linea di comando a riga di comando, ottiene il suo input tramite pipe STDIN e funziona immediatamente con un macOS appena installato:

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

Più formattato, lo script Perl è simile al seguente:

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

1

Puoi usarlo per comprimere con zlib:

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

E questo per sgonfiare:

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

4
unknown option '-z'su Ubuntu 16.04 eOpenSSL 1.0.2g 1 Mar 2016
Tino

2
stesso errore su Mac
K.-Michael Aye,

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.