Comment décompresser les données zlib sous UNIX?

107

J'ai créé des données compressées en zlib en Python, comme ceci:

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

(ou une doublure en-shell: echo -n '...' | python2 -c 'import sys,zlib; sys.stdout.write(zlib.compress(sys.stdin.read()))' > /tmp/data)

Maintenant, je veux décompresser les données dans un shell. Ni zcatni uncompresstravail:

$ 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

Il semble que j'ai créé un fichier de type gzip, mais sans en-tête. Malheureusement, je ne vois aucune option pour décompresser de telles données brutes dans la page de manuel gzip, et le paquet zlib ne contient aucun utilitaire exécutable.

Existe-t-il un utilitaire permettant de décompresser les données brutes zlib?

Mykhal
la source
Il y a beaucoup de réponses supplémentaires ici: stackoverflow.com/questions/3178566/deflate-command-line-tool
Jack O'Connor

Réponses:

141

Il est également possible de le décompresser en utilisant standard + , si vous n'en avez pas ou si vous voulez utiliser ou d'autres outils.
L'astuce consiste à ajouter le nombre magique gzip et la méthode de compression aux données réelles de zlib.compress:

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


Modifications : @ d0sboots a commenté: pour les données RAW Deflate, vous devez ajouter 2 octets nuls supplémentaires:
"\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x00"

Ce Q sur SO donne plus d'informations sur cette approche. Une réponse suggère qu'il existe également un pied de page de 8 octets.

Les utilisateurs @ Vitali-Kushner et @ mark-bessey ont enregistré un succès même avec des fichiers tronqués. Un pied de page gzip ne semble donc pas être absolument nécessaire.

@ tobias-kienzler a suggéré cette fonction pour le :
zlipd() (printf "\x1f\x8b\x08\x00\x00\x00\x00\x00" |cat - $@ |gzip -dc)

wkpark
la source
gzip ne fonctionne pas, mais zlib-flate fonctionne (flux de contenu de page pdf).
Daneel S. Yaitskov
70

L'utilisateur @tino a commenté ci-dessous la réponse OpenSSL mais je pense que cela devrait être séparé:

zlib-flate -uncompress < FILE

J'ai essayé cela et cela a fonctionné pour moi.

zlib-flatepeut être trouvé dans le paquet qpdf(dans Debian Squeeze et Fedora 23, selon les commentaires dans d’autres réponses)

Catskul
la source
3
Contrairement aux autres réponses, celle-ci fonctionne sous OS X.
polym
2
@polym, comment avez-vous été zlib-flate installé sur macOS? Je ne le vois nulle part.
Wildcard
4
@Wildcard désolé pour la réponse tardive. Je pense que cela est venu avec le qpdfpaquet que j'ai installé avec brewcomme mentionné dans le commentaire ci - dessus - ou regardez la dernière phrase de cette réponse :). Aussi, qpdfc'est vraiment cool, alors jetez-y un coup d'œil aussi si vous avez le temps!
polym
brew install qpdf, puis la commande ci-dessus :-) merci!
Fernando Gabrieli
60

J'ai trouvé une solution (une des possibles), elle utilise openssl :

$ openssl zlib -d < /tmp/data

ou

$ openssl zlib -d -in /tmp/data

* NOTE: La fonctionnalité zlib est apparemment disponible dans les versions récentes d'OpenSL> = 1.0.0 (OpenSSL doit être configuré / construit avec l'option zlib ou zlib-dynamic, cette dernière est la valeur par défaut)

Mykhal
la source
25
Sur Debian Squeeze (qui a OpenSSL 0.9.8), il y en a zlib-flatedans le qpdfpaquet. Il peut être utilisé comme zlib-flate -uncompress < FILE.
Tino
7
zlib a été supprimé des dernières versions d'OpenSSL, ce conseil est donc très utile. @Tino
Alexandr Kurilin
1
Merci. Cette solution offre une meilleure expérience de décompression de fichiers d’entrée courts que la réponse utilisant "gzip" ("openssl" autant que possible tout en "gzip" ayant abandonné l’impression "fin inattendue du fichier").
Daniel K.
2
@Tino cela devrait être une réponse séparée
Catskul
1
@Tino, il est également disponible via le package qpdf sur Fedora 23. Alexandr Kurilin, zlib est toujours disponible au format 1.0.2d-fips.
maxschlepzig
28

Je recommande pigz de Mark Adler , co-auteur de la bibliothèque de compression zlib. Exécutez pigzpour voir les drapeaux disponibles.

Tu remarqueras:

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

Vous pouvez décompresser en utilisant le -ddrapeau:

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

En supposant un fichier nommé 'test':

  • pigz -z test - crée un fichier compressé zlib nommé test.zz
  • pigz -d -z test.zz - convertit test.zz en fichier de test décompressé

Sur OSX, vous pouvez exécuter brew install pigz

snodnipper
la source
7
Bonne trouvaille! Il semble pouvoir détecter les fichiers zlib par lui-même, donc unpigz test.zzcela fonctionnera aussi.
Stéphane Chazelas
n'a pas décompressé mes données.
Cybernard le
1
@cybernard peut-être que vous n'avez pas de fichier zlib. vérifier avec:$>file hello.txt.zz hello.txt.zz: zlib compressed data
snodnipper
11

zlibimplémente la compression utilisée par gzip, mais pas le format de fichier. Au lieu de cela, vous devriez utiliser le gzipmodule , qui lui-même utilise zlib.

import gzip
s = '...'
with gzip.open('/tmp/data', 'w') as f:
    f.write(s)
REINSTATE MONICA - Jeremy Banks
la source
ok, mais ma situation est que j'ai des dizaines / centaines de milliers de ces fichiers créés, alors .. :)
1
alors ... vos fichiers sont incomplets. Peut-être devrez-vous les décompresser zlibet les recompresser gzip, si vous ne possédez pas encore les données d'origine.
Greg Hewgill
6
@mykhal, pourquoi avez-vous créé dix mille centaines de milliers de fichiers avant de vérifier que vous pouviez les décompresser?
3
harpyon, je peux les décompresser, je me demande simplement quels paramètres moins communs ou plus communs d'urility ou de zgip peuvent être utilisés pour cela, si je ne veux plus le refaire en python
3

Cela pourrait le faire:

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)

Puis lancez ça comme ça:

$ python expander.py data/*
REINSTATE MONICA - Jeremy Banks
la source
merci, je sais pour zlib.decompress. J'utiliserais probablement une fonction de marche. Je ne suis pas sûr que shell puisse gérer mon énorme quantité de fichiers avec glob wildcard :)
Le fichier créé par expand est toujours considéré comme une "donnée compressée zlib", à l'aide de la filecommande shell ? Comment c'est?
K.-Michael Aye
Nope ne fonctionne pas pour moi, même avec le faux en-tête.
Cybernard le
3

L'exemple de programme zpipe.c trouvé ici par Mark Adler lui-même (fourni avec la distribution source de la bibliothèque zlib) est très utile pour ces scénarios avec des données brutes zlib. Compiler avec cc -o zpipe zpipe.c -lzet pour décomprimer: zpipe -d < raw.zlib > decompressed. Il peut également faire la compression sans le -ddrapeau.

Henno Brandsma
la source
2

Sur macOS, qui est un UNIX entièrement conforme à POSIX (officiellement certifié!), OpenSSLN’a aucun zlibsupport, il n’existe pas non zlib-flateplus et bien que la première solution fonctionne aussi bien que toutes les solutions Python, la première solution nécessite que les données ZIP soient dans un fichier. et toutes les autres solutions vous obligent à créer un script Python.

Voici une solution basée sur Perl qui peut être utilisée comme ligne de commande one-line, reçoit son entrée via un tube STDIN et fonctionne immédiatement avec un macOS fraîchement installé:

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

Plus joliment formaté, le script Perl ressemble à ceci:

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

Vous pouvez utiliser ceci pour compresser avec zlib:

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

Et ceci pour dégonfler:

openssl enc -z -none -d < /file/to/deflate
Danny R
la source
4
Donne unknown option '-z'sur Ubuntu 16.04 etOpenSSL 1.0.2g 1 Mar 2016
Tino
2
même erreur sur Mac
K.-Michael Aye
-3
zcat -f infile > outfile 

travaille pour moi sur fedora25

sigxcpu
la source
1
zcatne fonctionne qu'avec des fichiers au format gzip.
Anthony Geoghegan