Як розпакувати дані zlib в UNIX?


106

Я створив дані, стиснуті zlib в Python, приблизно так:

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

(Або один вкладиш в оболонці: echo -n '...' | python2 -c 'import sys,zlib; sys.stdout.write(zlib.compress(sys.stdin.read()))' > /tmp/data)

Тепер я хочу розпакувати дані в оболонці. Ні, zcatні uncompressробота:

$ 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

Здається, я створив файл, схожий на gzip, але без заголовків. На жаль, я не бачу жодного варіанта розпакування таких необроблених даних на сторінці gzip man, а пакет zlib не містить жодної виконуваної утиліти.

Чи є утиліта для віджаття необроблених даних zlib?


Тут є багато додаткових відповідей: stackoverflow.com/questions/3178566/deflate-command-line-tool
Джек О'Коннор

Відповіді:


140

Можна також розпакувати його, використовуючи стандартний + , якщо у вас немає, або ви хочете використовувати або інші інструменти.
Трюк полягає в тому, щоб додати gzip магічне число та метод стиснення до фактичних даних із zlib.compress:

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

Зміни:
@ d0sboots прокоментував: Для даних RAW Deflate потрібно додати ще 2 нульові байти:
"\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x00"

Цей Q на SO дає більше інформації про цей підхід. Відповідь там говорить про те, що є також 8-байтний нижній колонтитул.

Користувачі @ Vitali-Kushner та @ mark-bessey повідомили про успіх навіть із усіченими файлами, тож gzip-колонтитул здається не обов'язковим.

@ tobias-kienzler запропонував цю функцію для :
zlipd() (printf "\x1f\x8b\x08\x00\x00\x00\x00\x00" |cat - $@ |gzip -dc)


gzip не працює, але zlib-flate робить (потік вмісту PDF-сторінки).
Даніель С. Яїтков

69

Користувач @tino прокоментував нижче відповіді OpenSSL, але, думаю, це має бути окремим:

zlib-flate -uncompress < FILE

Я спробував це, і це спрацювало на мене.

zlib-flateможна знайти в пакеті qpdf(в Debian Squeeze та Fedora 23, згідно з коментарями в інших відповідях)


3
На відміну від інших відповідей, ця працює на OS X.
полім

2
@polym, як ти zlib-flate встановився на macOS? Я його ніде не бачу.
Wildcard

4
@Wildcard вибачте за пізню відповідь. Я думаю, що це було в qpdfкомплекті з пакунком, який я встановив, brewяк згадувалося в коментарі вище, - або подивіться останнє речення цієї відповіді :). Крім того, qpdfце дійсно круто, тому подивіться і на це, якщо у вас є час!
полім

варити встановити qpdf, тоді команда, перелічена вище :-) дякую!
Фернандо Габріелі

60

Я знайшов рішення (одне з можливих), воно використовує openssl :

$ openssl zlib -d < /tmp/data

або

$ openssl zlib -d -in /tmp/data

* ПРИМІТКА: функціональність zlib, очевидно, доступна в останніх версіях openssl> = 1.0.0 (OpenSSL має бути налаштований / побудований за допомогою zlib або zlib-динамичного параметра, останній за замовчуванням)


25
На Debian Squeeze (у якого OpenSSL 0.9.8) є zlib-flateв qpdfпакеті. Це можна використовувати як zlib-flate -uncompress < FILE.
Тіно

7
zlib видалили з останніх версій OpenSSL, тому ця порада дуже корисна @Tino
Олександр Курилін

1
Дякую. Це рішення надає кращий досвід декомпресії коротких вхідних файлів, ніж відповідь за допомогою "gzip" ("openssl" декомпресується настільки, наскільки це можливо, тоді як "gzip" перервав друк "несподіваний кінець файлу").
Даніель К.

2
@Tino це має бути окрема відповідь
Catskul

1
@Tino, він також доступний через пакет qpdf на Fedora 23. Олександр Курилін, zlib все ще доступний у 1.0.2d-fips.
maxschlepzig

28

Я рекомендую pigz від Марка Адлера , співавтора бібліотеки стиснення zlib. Виконайте, pigzщоб побачити доступні прапори.

Ви помітите:

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

Ви можете скасувати скасування, використовуючи -dпрапор:

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

Припустимо, що файл називається "test":

  • pigz -z test - створює стислий файл zlib з назвою test.zz
  • pigz -d -z test.zz - перетворює test.zz у декомпресований тестовий файл

На OSX можна виконати brew install pigz


7
Гарна знахідка! Схоже, він може виявити файли zlib самостійно, тому також unpigz test.zzбуде працювати.
Стефан Шазелас

не розпаковував мої дані.
кібернард

1
@cybernard, можливо, у вас немає файлу zlib. перевірити:$>file hello.txt.zz hello.txt.zz: zlib compressed data
snodnipper

11

zlibреалізує стиснення, використовуване gzip, але не формат файлу. Натомість слід використовувати gzipмодуль , який сам використовує zlib.

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

ОК, але моя ситуація полягає в тому, що у мене створені десятки / сотні тисяч цих файлів, так що .. :)

1
тому ... ваші файли неповні. Можливо, вам доведеться розпакувати їх zlibі повторно скопіювати gzip, якщо у вас ще немає оригінальних даних.
Грег Хьюгілл

6
@mykhal, чому ти створив десять / сто тисяч файлів, перш ніж перевірити, що ти насправді ти можеш їх розпакувати?

3
Гарпіон, я можу їх розпакувати, я просто цікавлюсь, які менш чи більш поширені параметри urtility або zgip можуть бути використані для цього, якщо я не хочу робити це знову в python

3

Це може зробити це:

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)

Потім запустіть його так:

$ python expander.py data/*

дякую, я знаю про zlib.decompress. ймовірно, я б використовував якусь функцію прогулянки. Я не впевнений, чи оболонка обробляла б мою величезну кількість файлів за допомогою глобального шаблону :)

Файл, створений розширеним, все ще перевіряється як "стислі дані zlib" для мене, використовуючи команду shell file? Як у тому, що?
K.-Michael Aye

nope не працює для мене навіть із підробленим заголовком.
кібернард

3

Прикладна програма, zpipe.c знайдена тут самим Марком Адлером (постачається з розповсюдженням джерел бібліотеки zlib), дуже корисна для цих сценаріїв із необробленими даними zlib. Компіляція з cc -o zpipe zpipe.c -lzі розпаковувати: zpipe -d < raw.zlib > decompressed. Він також може робити стиснення без -dпрапора.


2

У macOS, який є повним UNIX-сумісним UNIX (офіційно сертифікований!), OpenSSLНемає zlibпідтримки, немає zlib-flateі, і коли перше рішення працює так само, як і всі рішення Python, для першого рішення потрібні дані ZIP, щоб вони були у файлі а всі інші рішення змушують вас створити сценарій Python.

Ось рішення на основі Perl, яке можна використовувати як однолінійний командний рядок, отримує свій вхід через трубу STDIN і працює з коробки із щойно встановленим 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;'

Гарніший формат, сценарій Perl виглядає так:

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

1

Ви можете використовувати це для стискання зліб:

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

І це спустіть:

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

4
Дає unknown option '-z'на Ubuntu 16.04 таOpenSSL 1.0.2g 1 Mar 2016
Тіно

2
така ж помилка на Mac
K.-Michael Aye

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.