Jak zdekompresować dane zlib w systemie UNIX?

106

W Pythonie utworzyłem dane skompresowane zlib, w następujący sposób:

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

(lub jednowarstwowy w skorupce echo -n '...' | python2 -c 'import sys,zlib; sys.stdout.write(zlib.compress(sys.stdin.read()))' > /tmp/data)

Teraz chcę rozpakować dane w powłoce. Ani zcatnie uncompressdziała:

$ 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

Wygląda na to, że utworzyłem plik podobny do gzipa, ale bez nagłówków. Niestety nie widzę żadnej opcji rozpakowywania takich surowych danych na stronie podręcznika gzip, a pakiet zlib nie zawiera żadnego narzędzia wykonywalnego.

Czy istnieje narzędzie do rozpakowywania surowych danych zlib?

mykhal
źródło
Istnieje wiele dodatkowych odpowiedzi tutaj: stackoverflow.com/questions/3178566/deflate-command-line-tool
Jack O'Connor

Odpowiedzi:

140

Można go również zdekompresować za pomocą standardowego + , jeśli nie masz lub chcesz użyć lub innych narzędzi.
Sztuką jest dodanie magicznej liczby gzip i metoda kompresji do rzeczywistych danych z zlib.compress:

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

Edycje:
@ d0sboots skomentował: W przypadku danych RAW Deflate należy dodać jeszcze 2 bajty puste:
"\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x00"

To pytanie dotyczące SO zawiera więcej informacji na temat tego podejścia. Odpowiedź sugeruje, że istnieje również 8-bajtowa stopka.

Użytkownicy @ Vitali-Kushner i @ mark-bessey zgłosili sukces nawet przy obciętych plikach, więc stopka gzip nie wydaje się ściśle wymagana.

@ tobias-kienzler zasugerował tę funkcję dla :
zlipd() (printf "\x1f\x8b\x08\x00\x00\x00\x00\x00" |cat - $@ |gzip -dc)

wkpark
źródło
gzip nie działa, ale działa zlib-flate (strumień treści strony pdf).
Daneel S. Yaitskov
69

Użytkownik @tino skomentował odpowiedź OpenSSL, ale myślę, że powinna być osobna:

zlib-flate -uncompress < FILE

Próbowałem tego i zadziałało to dla mnie.

zlib-flatemożna znaleźć w pakiecie qpdf(w Debian Squeeze i Fedorze 23, zgodnie z komentarzami w innych odpowiedziach)

Catskul
źródło
3
W przeciwieństwie do innych odpowiedzi, ta działa na OS X.
polym
2
@polym, w jaki sposób został zlib-flate zainstalowany na macOS? Nigdzie tego nie widzę.
Wildcard
4
@Wildcard przepraszamy za spóźnioną odpowiedź. Myślę, że przyszedł z qpdfpakietem, który zainstalowałem, brewjak wspomniano w komentarzu powyżej - lub spójrz na ostatnie zdanie tej odpowiedzi :). Ponadto qpdfjest naprawdę fajny, więc spójrz na to, jeśli masz czas!
polim
napar zainstalować qpdf, a następnie polecenie wymienione powyżej :-) dziękuję!
Fernando Gabrieli
60

Znalazłem rozwiązanie (jedno z możliwych), używa ono openssl :

$ openssl zlib -d < /tmp/data

lub

$ openssl zlib -d -in /tmp/data

* UWAGA: funkcjonalność zlib jest widocznie dostępna w najnowszych wersjach openssl> = 1.0.0 (OpenSSL musi być skonfigurowany / zbudowany z opcją zlib lub zlib-dynamic, ta ostatnia jest domyślna)

mykhal
źródło
25
Na Debian Squeeze (który ma OpenSSL 0.9.8) jest zlib-flatew qpdfpakiecie. Może być używany jak zlib-flate -uncompress < FILE.
Tino
7
zlib został usunięty z najnowszych wersji OpenSSL, więc ta wskazówka jest bardzo pomocna @Tino
Alexandr
1
Dzięki. To rozwiązanie zapewnia lepsze doświadczenie w dekompresji krótkich plików wejściowych niż odpowiedź przy użyciu „gzip” („openssl” dekompresuje tyle, ile może, podczas gdy „gzip” przerywa drukowanie „nieoczekiwanego końca pliku”).
Daniel K.
2
@Tino powinna to być osobna odpowiedź
Catskul
1
@Tino, jest również dostępny poprzez pakiet qpdf na Fedorze 23. Alexandr Kurilin, zlib jest nadal dostępny w wersji 1.0.2d-fips.
maxschlepzig
28

Polecam pigza od Marka Adlera , współautora biblioteki kompresji zlib. Wykonaj, pigzaby zobaczyć dostępne flagi.

Zauważysz:

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

Możesz rozpakować za pomocą -dflagi:

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

Zakładając plik o nazwie „test”:

  • pigz -z test - tworzy skompresowany plik zlib o nazwie test.zz
  • pigz -d -z test.zz - konwertuje test.zz w zdekompresowany plik testowy

W OSX można wykonać brew install pigz

snodnipper
źródło
7
Dobre znalezisko! Wygląda na to, że może sam wykryć pliki zlib, więc również unpigz test.zzbędzie działać.
Stéphane Chazelas,
nie zdekompresowałem moich danych.
cybernard
1
@cybernard być może nie masz pliku zlib. sprawdź za pomocą:$>file hello.txt.zz hello.txt.zz: zlib compressed data
snodnipper
11

zlibimplementuje kompresję używaną przez gzip, ale nie format pliku. Zamiast tego powinieneś użyć gzipmodułu , który sam używa zlib.

import gzip
s = '...'
with gzip.open('/tmp/data', 'w') as f:
    f.write(s)
Jeremy Banks
źródło
ok, ale moja sytuacja jest taka, że ​​utworzyłem dziesiątki / setki tysięcy tych plików, więc .. :)
1
więc ... twoje pliki są niekompletne. Być może będziesz musiał je rozpakować zlibi ponownie skompresować gzip, jeśli nadal nie masz oryginalnych danych.
Greg Hewgill,
6
@mykhal, dlaczego stworzyłeś dziesięćset tysięcy plików przed sprawdzeniem, czy rzeczywiście możesz je zdekompresować?
3
harpyon, mogę je rozpakować, po prostu zastanawiam się, które mniej lub bardziej powszechne urility lub ustawienia zgip mogą być wykorzystane do tego, jeśli nie chcę, aby to zrobić w Pythonie ponownie
3

Może to zrobić:

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)

Następnie uruchom go w następujący sposób:

$ python expander.py data/*
Jeremy Banks
źródło
dzięki, wiem o zlib.decompress. prawdopodobnie użyłbym funkcji chodzenia. Nie jestem pewien, czy powłoka będzie obsługiwać moją ogromną ilość plików z glob zamiennika :)
Plik, który jest tworzony przez rozwinięte, nadal jest sprawdzany jako „skompresowane dane zlib” dla mnie za pomocą filepolecenia powłoki ? W jaki sposób?
K.-Michael Aye
nope nie działa dla mnie nawet z fałszywym nagłówkiem.
cybernard
3

Przykładowy program zpipe.c znaleziony tutaj przez samego Marka Adlera (pochodzi ze źródłowej dystrybucji biblioteki zlib) jest bardzo przydatny w tych scenariuszach z surowymi danymi zlib. Skompilować cc -o zpipe zpipe.c -lzi dekompresji: zpipe -d < raw.zlib > decompressed. Może także wykonywać kompresję bez -dflagi.

Henno Brandsma
źródło
2

Na macOS, który jest w pełni zgodny z POSIX-em UNIX (formalnie certyfikowany!), Nie OpenSSLma zlibwsparcia, nie ma żadnego z zlib-flatenich, a podczas gdy pierwsze rozwiązanie działa tak samo jak wszystkie rozwiązania Python, pierwsze rozwiązanie wymaga, aby dane ZIP znajdowały się w pliku a wszystkie inne rozwiązania zmuszają cię do stworzenia skryptu Python.

Oto rozwiązanie oparte na Perlu, które może być użyte jako jedno-liniowy wiersz poleceń, pobiera dane wejściowe za pośrednictwem potoku STDIN i działa od razu po zainstalowaniu systemu macOS:

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

Bardziej sformatowany skrypt Perla wygląda następująco:

use Compress::Raw::Zlib;
my $decompressor = new Compress::Raw::Zlib::Inflate();
my $output;
undef $/;
$decompressor->inflate(<>, $output);
print $output;
Mecki
źródło
1

Możesz użyć tego do kompresji za pomocą zlib:

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

I to do spuszczenia:

openssl enc -z -none -d < /file/to/deflate
Danny R.
źródło
4
Daje unknown option '-z'na Ubuntu 16.04 iOpenSSL 1.0.2g 1 Mar 2016
Tino
2
ten sam błąd na Macu
K.-Michael Aye
-3
zcat -f infile > outfile 

działa dla mnie na fedora25

sigxcpu
źródło
1
zcatdziała tylko z plikami w formacie gzip.
Anthony Geoghegan