Làm cách nào để giải nén dữ liệu zlib trong UNIX?


106

Tôi đã tạo dữ liệu nén zlib trong Python, như thế này:

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

(hoặc một lớp lót trong vỏ echo -n '...' | python2 -c 'import sys,zlib; sys.stdout.write(zlib.compress(sys.stdin.read()))' > /tmp/data:)

Bây giờ, tôi muốn giải nén dữ liệu trong shell. Không zcatphải cũng không uncompresslàm việc:

$ 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

Có vẻ như tôi đã tạo tệp giống như gzip, nhưng không có bất kỳ tiêu đề nào. Thật không may, tôi không thấy bất kỳ tùy chọn nào để giải nén dữ liệu thô như vậy trong trang gzip man và gói zlib không chứa bất kỳ tiện ích thực thi nào.

Có một tiện ích để giải nén dữ liệu zlib thô?


Có nhiều câu trả lời bổ sung tại đây: stackoverflow.com/questions/3178566/deflate-command-line-tool
Jack O'Connor

Câu trả lời:


140

Cũng có thể giải nén nó bằng + tiêu chuẩn , nếu bạn không có hoặc muốn sử dụng hoặc các công cụ khác.
Mẹo nhỏ là thêm số ma thuật gzip và phương thức nén vào dữ liệu thực tế từ zlib.compress:

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

Chỉnh sửa:
@ d0sboots đã nhận xét: Đối với dữ liệu RAW Deflate, bạn cần thêm 2 byte null:
"\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x00"

Q này trên SO cung cấp thêm thông tin về phương pháp này. Một câu trả lời ở đó cho thấy rằng cũng có một chân trang 8 byte.

Người dùng @ Vitali-Kushner và @ mark-ambsey đã báo cáo thành công ngay cả với các tệp bị cắt bớt, do đó, một chân trang gzip dường như không bắt buộc.

@ tobias-kienzler đã đề xuất chức năng này cho :
zlipd() (printf "\x1f\x8b\x08\x00\x00\x00\x00\x00" |cat - $@ |gzip -dc)


gzip không hoạt động, nhưng zlib-flate thì có (luồng nội dung trang pdf).
Daneel S. Yaitskov

69

Người dùng @tino đã nhận xét bên dưới câu trả lời OpenSSL nhưng tôi nghĩ điều này nên tách biệt:

zlib-flate -uncompress < FILE

Tôi đã thử điều này và nó đã làm việc cho tôi.

zlib-flatecó thể được tìm thấy trong gói qpdf(trong Debian Squeeze và Fedora 23, theo nhận xét trong các câu trả lời khác)


3
Ngược lại với các câu trả lời khác, câu trả lời này hoạt động trên OS X.
polym

2
@polym, bạn đã zlib-flate cài đặt như thế nào trên macOS? Tôi không thấy nó ở đâu cả.
tự đại diện

4
@Wildcard xin lỗi vì phản hồi muộn. Tôi nghĩ rằng nó đi kèm với qpdfgói mà tôi đã cài đặt brewnhư được đề cập trong nhận xét ở trên - hoặc xem câu cuối cùng của câu trả lời này :). Ngoài ra, qpdflà thực sự mát mẻ, vì vậy hãy xem nó nếu bạn có thời gian!
polym

brew cài đặt qpdf, sau đó lệnh được liệt kê ở trên :-) cảm ơn bạn!
Fernando Gabrieli

60

Tôi đã tìm thấy một giải pháp (một trong những giải pháp khả thi), đó là sử dụng openssl :

$ openssl zlib -d < /tmp/data

hoặc là

$ openssl zlib -d -in /tmp/data

* LƯU Ý: Chức năng zlib rõ ràng khả dụng trong các phiên bản openssl gần đây> = 1.0.0 (OpenSSL phải được định cấu hình / xây dựng với tùy chọn zlib hoặc zlib-Dynamic, sau này là mặc định)


25
Trên Debian Squeeze (có OpenSSL 0.9.8) có zlib-flatetrong qpdfgói. Nó có thể được sử dụng như thế nào zlib-flate -uncompress < FILE.
Tino

7
zlib đã bị xóa khỏi các phiên bản mới nhất của OpenSSL, vì vậy mẹo này rất hữu ích @Tino
Alexandr Kurilin

1
Cảm ơn. Giải pháp này cung cấp trải nghiệm tốt hơn trong việc giải nén các tệp đầu vào ngắn hơn so với câu trả lời bằng cách sử dụng "gzip" ("openssl" giải nén hết mức có thể trong khi "gzip" hủy bỏ in "kết thúc tệp không mong muốn").
Daniel K.

2
@Tino đây phải là một câu trả lời riêng biệt
Catskul

1
@Tino, nó cũng có sẵn thông qua gói qpdf trên Fedora 23. Alexandr Kurilin, zlib vẫn có sẵn trong 1.0.2d-fips.
maxschlepzig

28

Tôi đề nghị pigz từ Mark Adler , đồng tác giả của thư viện nén zlib. Thực hiện pigzđể xem các cờ có sẵn.

Bạn sẽ nhận thấy:

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

Bạn có thể giải nén bằng -dcờ:

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

Giả sử một tệp có tên 'test':

  • pigz -z test - tạo tệp nén zlib có tên test.zz
  • pigz -d -z test.zz - chuyển đổi test.zz thành tệp thử nghiệm giải nén

Trên OSX bạn có thể thực thi brew install pigz


7
Tìm tốt Có vẻ như nó có thể tự phát hiện các tệp zlib, do đó unpigz test.zzcũng sẽ hoạt động.
Stéphane Chazelas

đã không giải nén dữ liệu của tôi.
gian mạng

1
@cybernard có lẽ bạn không có tệp zlib. kiểm tra với:$>file hello.txt.zz hello.txt.zz: zlib compressed data
snodnipper

11

zlibthực hiện nén được sử dụng bởi gzip, nhưng không phải là định dạng tệp. Thay vào đó, bạn nên sử dụng gzipmô-đun , chính nó sử dụng zlib.

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

ok, nhưng tình hình của tôi là tôi có hàng chục / hàng trăm ngàn tệp được tạo, vì vậy .. :)

1
vì vậy ... các tập tin của bạn không đầy đủ. Có lẽ bạn sẽ phải giải nén chúng zlibvà giải nén chúng gzip, nếu bạn vẫn không có dữ liệu gốc.
Greg Hewgill

6
@mykhal, tại sao bạn tạo mười / trăm ngàn tệp trước khi kiểm tra xem bạn thực sự có thể giải nén chúng không?

3
harpyon, tôi có thể giải nén chúng, tôi chỉ thắc mắc mà ít hoặc chung urility hoặc cài đặt zgip hơn có thể được sử dụng cho rằng, nếu tôi không muốn làm điều đó trong python nữa

3

Điều này có thể làm điều đó:

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)

Sau đó chạy nó như thế này:

$ python expander.py data/*

cảm ơn, tôi biết về zlib.decompress. có lẽ tôi sẽ sử dụng một số chức năng đi bộ. Tôi không chắc chắn nếu shell sẽ xử lý số lượng tệp khổng lồ của tôi bằng thẻ đại diện toàn cầu :)

Tập tin được tạo bằng cách mở rộng vẫn kiểm tra là "dữ liệu nén zlib" đối với tôi, bằng cách sử dụng filelệnh shell ? Làm như thế nào?
K.-Michael Aye

Không có tác dụng với tôi ngay cả với tiêu đề giả.
gian mạng

3

Chương trình ví dụ zpipe.c được tìm thấy ở đây bởi chính Mark Adler (đi kèm với phân phối nguồn của thư viện zlib) rất hữu ích cho các tình huống này với dữ liệu zlib thô. Biên dịch với cc -o zpipe zpipe.c -lzvà giải nén : zpipe -d < raw.zlib > decompressed. Nó cũng có thể thực hiện nén mà không cần -dcờ.


2

Trên macOS, một UNIX tuân thủ POSIX đầy đủ (được chứng nhận chính thức!), OpenSSLKhông có zlibhỗ trợ, không có zlib-flategiải pháp đầu tiên nào hoạt động tốt như tất cả các giải pháp Python, giải pháp đầu tiên yêu cầu dữ liệu ZIP phải có trong một tệp và tất cả các giải pháp khác buộc bạn phải tạo tập lệnh Python.

Đây là một giải pháp dựa trên Perl có thể được sử dụng như một lớp lót dòng lệnh, lấy đầu vào của nó thông qua ống STDIN và hoạt động ngay lập tức với macOS được cài đặt mới:

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

Nicer được định dạng, tập lệnh Perl trông như thế này:

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

1

Bạn có thể sử dụng điều này để nén với zlib:

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

Và điều này để xì hơi:

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

4
Cung cấp unknown option '-z'trên Ubuntu 16.04 vàOpenSSL 1.0.2g 1 Mar 2016
Tino

2
lỗi tương tự trên Mac
K.-Michael Aye

-3
zcat -f infile > outfile 

làm việc cho tôi trên fedora25


1
zcatchỉ hoạt động với các tập tin ở định dạng gzip.
Anthony Geoghegan
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.