2010-07-05 38 views
68

Poszukuję otoki linii poleceń dla algorytmu DEFLATE.Narzędzie Deflate z wiersza poleceń

Mam plik (gob blob), który jest skompresowany przy użyciu DEFLATE, i chcę go zdekompresować. Wydaje się, że polecenie gzip nie ma opcji bezpośredniego użycia algorytmu DEFLATE, zamiast formatu gzip.

Idealnie szukam standardowego narzędzia Unix/Linux, które może to zrobić.

edit: To wyjście uzyskać podczas próby użycia gzip dla mojego problemu:

$ cat .git/objects/c0/fb67ab3fda7909000da003f4b2ce50a53f43e7 | gunzip 

gzip: stdin: not in gzip format 

Odpowiedz

5

AKTUALIZACJA: Mark Adler zauważył, że glister nie są surowymi strumieniami DEFLATE, ale strumieniami zlib. Te mogą być rozpakowane przez narzędzie pigz, który pochodzi fabrycznie zapakowane w kilku dystrybucjach Linux:

$ cat foo.txt 
file foo.txt! 

$ git ls-files -s foo.txt 
100644 7a79fc625cac65001fb127f468847ab93b5f8b19 0 foo.txt 

$ pigz -d < .git/objects/7a/79fc625cac65001fb127f468847ab93b5f8b19 
blob 14file foo.txt! 

mój oryginalny odpowiedź, utrzymywane z przyczyn historycznych:

Jeśli rozumiem aluzję w Wikipedia article wymieniony autor: Marc van Kempen, możesz bezpośrednio użyć puff.c z zlib.

Jest to mały przykład:

#include <assert.h> 
#include <string.h> 
#include "puff.h" 

int main(int argc, char **argv) { 
    unsigned char dest[ 5 ]; 
    unsigned long destlen = 4; 
    const unsigned char *source = "\x4B\x2C\x4E\x49\x03\x00"; 
    unsigned long sourcelen = 6;  
    assert(puff(dest, &destlen, source, &sourcelen) == 0); 
    dest[ 4 ] = '\0'; 
    assert(strcmp(dest, "asdf") == 0); 
} 
+3

Tak, spojrzałem na to. Ale zdecydowanie wolałbym powszechnie pakowane narzędzie. –

+0

Dobrze, dokonano bardzo późnej edycji teraz z działającym minimalnym przykładem. – mkluwe

+0

To nie zadziała. glip blobs to strumienie zlib, a nie raw deflate. To rozwiązanie działa na deflację surową. puff nie przetwarza nagłówka i zwiastuna zlib. Jeśli chcesz narzędzie, możesz użyć [pigz] (http://zlib.net/pigz), które rozpakuje format zlib z opcją '-dz', a także wygeneruje format zlib za pomocą' -z' . –

1

Zobacz http://en.wikipedia.org/wiki/DEFLATE#Encoder_implementations

Wymienia szereg wdrożeń oprogramowania, w tym gzip, tak że powinno działać. Czy próbowałeś po prostu uruchomić gzip na tym pliku? Czy nie rozpoznaje automatycznie formatu?

Skąd wiadomo, że jest skompresowany przy użyciu DEFLATE? Jakie narzędzie zostało użyte do skompresowania pliku?

+0

Zobacz na dole tej strony: http://progit.org/book/ch9-2.html Gzip implementuje DEFLATE, ale nie wygląda na to, że możesz bezpośrednio zastosować algorytm. Gzip spodziewa się, że dane będą w formacie gzip (który dodaje kilka nagłówków i innych informacji związanych z danymi DEFLATE). (Właśnie edytowałem swój post, aby dołączyć dane wyjściowe z gunzip). –

+2

No dobrze, więc dane są kompresowane za pomocą biblioteki zlib, to znaczy, że możesz dekompresować używając zlib! Możesz wypróbować ruby, perl lub inne wiązanie, aby wymazać prosty skrypt deflate. Lub jeśli nie boisz się spróbować swoich sił w kompilowaniu programu ac, spróbuj tego: http://www.zlib.net/zlib_how.html –

+0

NB Po prostu wypróbowałem to i zpipe.c działa na obiektach git, skompiluj z 'gcc -o zpipe zpipe.c -I/ścieżka/do/zlib.h -l/ścieżka/do/zlib -lZ' zastosowanie: ./zpipe -d <.git/obiektów/83/535d1693580f04824a2ddd22bd241fd00533d8 (użyj -d do dekompresji) –

0

Dlaczego nie można po prostu użyć narzędzi git, aby uzyskać dostęp do danych? To powinno być w stanie odczytać dowolny obiekt git:

git show --pretty=raw <object SHA-1> 
+3

Przygotowuję się do małego git-workshopu, który zamierzam dać wkrótce. Jednym z przykładów jest pokazanie, co "git add" robi ręcznie. De-compressing blob za pomocą samego git nie ma sensu, ponieważ chcę pokazać funkcję underlayingu. Prawdopodobnie zakończę używanie rubinu lub perla, ale miałem nadzieję, że będę mógł trzymać się onlinera. –

+2

Lub 'git cat-file -p c0fb67ab3fda7909000da003f4b2ce50a53f43e7' –

+0

@igorw: tylko tak długo, jak obiekt znajduje się w drzewie. wiedza o znalezieniu niektórych obiektów git w "lost + found" (po tym, jak fsck.ext4 je tam umieścił) jest całkiem przydatna ... – akira

46

Coś wydrukuje zawartość surowego poniżej, w tym "$ type $ długość \ 0" Header:

perl -MCompress::Zlib -e 'undef $/; print uncompress(<>)' \ 
    < .git/objects/27/de0a1dd5a89a94990618632967a1c86a82d577 
+0

[Niepoprawnie] Puste wyjście i zerowy kod wyjścia na * surowym * strumieniu deflacyjnym bez znacznika '78' i końcowego crc. – ulidtko

+0

Działa dla mnie również z dowolnymi danymi bezpośrednio skompresowanymi w 'C' używając zlib, więc niesamowita odpowiedź. I jak zwykle: w końcu większość światowych problemów można rozwiązać za pomocą jednego liniowca PERL;) – Mecki

9

Oto przykład złamanie otwarte commit obiekt w Pythonie:

$ git show 
commit 0972d7651ff85bedf464fba868c2ef434543916a 
# all the junk in my commit... 
$ python 
>>> import zlib 
>>> file = open(".git/objects/09/72d7651ff85bedf464fba868c2ef434543916a") 
>>> data = file.read() 
>>> print data 
# binary garbage 
>>> unzipped_data = zlib.decompress(data) 
>>> print unzipped_data 
# all the junk in my commit! 

Co widać tam jest prawie identyczny z wyjściem „git kot akt -p [hash]”, oprócz tego, że komenda nie drukuje nagłówka (” commit ", po którym następuje wielkość treść i bajt zerowy).

+4

W zależności od systemu operacyjnego możesz chcieć dodać przełącznik "rb" dla "otwartego" jak: 'file = open (". git/objects/09/72d7651ff85bedf464fba868c2ef434543916a "," rb ")' –

+3

+1 za wyjaśnienie formatu nagłówka. – ntc2

38

pythonic jedna wkładka:

$> python -c "import zlib,sys;print \ 
      repr(zlib.decompress(sys.stdin.read()))" < $IN 
+0

'repr (...) 'wydaje się zawijać wszystko w cudzysłów (' '...' '), więc musiałem go usunąć (dekompresując skompresowany plik JSON zlib). –

+0

To pięknie działa! –

+0

Właściwie jest to 'python -c" importuj zlib, sys; print (zlib.decompress (sys.stdin.buffer.read()) .ododrębnij ('utf8')) "<$ IN", jeśli spodziewasz się pliku utf8 dla wystąpienie w Pythonie 3 –

14

Tutaj Ruby jedna wkładka (CD .git/pierwszy i identyfikacji ścieżki do każdego obiektu)

ruby -rzlib -e 'print Zlib::Inflate.new.inflate(STDIN.read)' < ./74/c757240ec596063af8cd273ebd9f67073e1208 
+0

, aby usunąć nagłówek [rozmiaru bloba]: 'ruby -rzlib -e 'print Zlib :: Inflate.inflate ($ stdin.read) .split (" \ x00 ") [1 ..- 1] .join '<.git/objects/abc' – yachi

6

obiektów git są kompresowane zlib zamiast gzip, więc albo używając zlib, aby ją zdekompresować, albo polecenie git, tj. git cat-file -p <SHA1>, aby wydrukować zawartość.

+3

Jak [Jack wskazuje powyżej] (http://stackoverflow.com/a/6539072/470844), wyjście 'git cat-file -p ' jest * nie * kompletna zawartość dekompresji zlib dla '.git/objects/'. Różnica jest kluczowa, jeśli próbujesz zaimplementować kalkulator skrótu zatwierdzenia Git ... – ntc2

+0

Opcja -p pretty print jest zaletą, gdy chcesz zrozumieć zawartość obiektu. Nieskompresowanie obiektu drzewa za pomocą świni nie zapewni wyniku czytelnego dla człowieka. – Vortexfive

6

Wygląda Mark Adler ma nam w głowie i napisał przykład, jak to zrobić z: http://www.zlib.net/zpipe.c

To kompiluje z niczym więcej niż gcc -lz i nagłówków zlib zainstalowane. Skopiowałem wynikowy plik binarny do mojego /usr/local/bin/zpipe podczas pracy z plikami git.

8

Dostałem zmęczony, nie mając dobre rozwiązanie dla tego, więc umieścić coś na KMP:

https://github.com/jezell/zlibber

Teraz można po prostu rurę do nadmuchać/polecenia opróżnić.

+0

Jak korzystać z tego pakietu? – RHPT

+0

@RHPT W systemie Windows wpisz "type #### | inflate", gdzie #### jest sumą kontrolną obiektu. – mhenry1384

24

Można używać zlib-Flate, tak:

cat .git/objects/c0/fb67ab3fda7909000da003f4b2ce50a53f43e7 \ 
    | zlib-flate -uncompress; echo 

Jest tam domyślnie na moim komputerze, ale to część qpdf - tools for and transforming and inspecting PDF files jeśli trzeba go zainstalować.

Na końcu polecenia pojawiło się echo, ponieważ łatwiej jest odczytać wynik w ten sposób.

+1

To działało na Ubuntu 14.04 bez żadnej instalacji – Ricardo

+1

Nie trzeba dla kota: zlib-flate -uncompress <.git/objects/c0/fb67ab3fda7909000da003f4b2ce50a53f43e7 –

42

Można to zrobić za pomocą narzędzia wiersza poleceń OpenSSL:

openssl zlib -d < $IN > $OUT 

Niestety, przynajmniej na Ubuntu The zlib komenda jest wyłączona w konfiguracji domyślnej kompilacji (--no-zlib--no-zlib-dynamic), więc trzeba by skompilować openssl ze źródła, aby go użyć. Ale jest domyślnie włączony na Arch, na przykład.

Edytuj: Wygląda na to, że polecenie zlib nie jest już obsługiwane w Arch. Ta odpowiedź nie może być przydatny już :(

+10

Zauważ, że pod-polecenie 'zlib' (i opcja' -z 'do' pod-komenda enc) * nie * jest dostępne, jeśli twoja kompilacja openssl została skonfigurowana z domyślnymi opcjami, które obejmują '--no-zlib' i' --no-zlib-dynamic'. Tak więc ta odpowiedź działa tylko wtedy, gdy twój openssl został skompilowany z prefiksem 'no-' usuniętym z jednej z tych opcji konfiguracyjnych. Możesz powiedzieć, szukając '-DZLIB' w wyjściu z' openssl version -f' – Hercynium

+0

@Hercynium dzięki! W szczególności tak jest w przypadku Ubuntu 14.04 :( –

+0

działa dobrze na moim serwerze Fedora – fuzzyTew

1

Znalazłem to pytanie, patrząc na obejście z błędem z narzędziem -text w nowej wersji klienta hadoop dfs Właśnie zainstalowałem. Narzędzie -text działa jak cat, z wyjątkiem jeśli odczytany plik jest skompresowany, przezroczyście rozpakowuje się i wypisuje zwykły tekst (stąd nazwa):

Odpowiedzi już zamieszczone były zdecydowanie pomocne, ale niektóre z nich mają jeden problem, gdy mamy do czynienia z wielkościami Hadoop dane - wczytują wszystko do pamięci przed dekompresją.

Tak, oto moje wariacje na Perl i Python odpowiedzi powyżej, które nie mają tego ograniczenia:

Python:

hadoop fs -cat /path/to/example.deflate | 
    python -c 'import zlib,sys;map(lambda b:sys.stdout.write(zlib.decompress(b)),iter(lambda:sys.stdin.read(4096),""))' 

Perl:

hadoop fs -cat /path/to/example.deflate | 
    perl -MCompress::Zlib -e 'print uncompress($buf) while sysread(STDIN,$buf,4096)' 

Uwaga Użycie sub-polecenia -cat, zamiast -text. Jest tak, że moje obejście się nie psuje, po naprawieniu błędu. Przepraszamy za czytelność wersji python.

17

Spróbuj następującą komendę: potrzebne są

printf "\x1f\x8b\x08\x00\x00\x00\x00\x00" | cat - .git/objects/c0/fb67ab3fda7909000da003f4b2ce50a53f43e7 | gunzip 

żadnych narzędzi zewnętrznych.

Źródło: How to uncompress zlib data in UNIX? na unix SE

+1

Pojawia się błąd "nieoczekiwanego końca pliku", ale nadal jest to zgrabny hack – Eric

+2

Po prostu przedrostek z nagłówkiem pliku gzip. –

+1

Tam też go znalazłem - dodał 'zlipd() (printf" \ x1f \ x8b \ x08 \ x00 \ x00 \ x00 \ x00 \ x00 "| cat - $ @ | gzip -dc)" do mojego '.bashrc' teraz :) –

5
// save this as deflate.go 

package main 

import (
    "compress/zlib" 
    "io" 
    "os" 
    "flag" 
) 

var infile = flag.String("f", "", "infile") 

func main() { 
    flag.Parse() 
    file, _ := os.Open(*infile) 

    r, err := zlib.NewReader(file) 
    if err != nil { 
     panic(err) 
    } 
    io.Copy(os.Stdout, r) 

    r.Close() 
} 

$ go build deflate.go 
$ ./deflate -f .git/objects/c0/fb67ab3fda7909000da003f4b2ce50a53f43e7 
+0

Działa pięknie na macOS 10.11, dzięki! Musiałem zainstalować Go (co zresztą zamierzałem zrobić) z [oficjalnej strony internetowej] (https://golang.org/dl/), wtedy zadziałało idealnie. Napisałeś to sam? Nie jest to miłe z powodu nieoczekiwanych argumentów. :) – Wildcard

0

pigz może to zrobić:

apt-get install pigz 
unpigz -c .git/objects/c0/fb67ab3fda7909000da003f4b2ce50a53f43e7 
0
const zlib = require("zlib"); 
const adler32 = require("adler32"); 
const data = "hello world~!"; 
const chksum = adler32.sum(new Buffer(data)).toString(16); 
console.log("789c",zlib.deflateRawSync(data).toString("hex"),chksum); 
// or 
console.log(zlib.deflateSync(data).toString("hex")); 
1

obiekty git są zlib strumienie (nie surowe deflate) . pigz rozpakuje te z opcją -dz.

Powiązane problemy