Как распаковать данные zlib в UNIX?

107

Я создал 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-подобный файл, но без заголовков. К сожалению, я не вижу никакой возможности распаковать такие необработанные данные на man-странице gzip, и пакет zlib не содержит никакой исполняемой утилиты.

Есть ли утилита для распаковки сырых данных zlib?

mykhal
источник
Здесь можно найти много дополнительных ответов: stackoverflow.com/questions/3178566/deflate-command-line-tool
Джек О'Коннор,

Ответы:

141

Также можно распаковать его, используя стандартный + , если у вас его нет, или вы хотите использовать или другие инструменты.
Хитрость заключается в том, чтобы добавить магический номер 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"

Этот вопрос о SO дает больше информации об этом подходе. Ответ там предполагает, что есть также 8-байтовый нижний колонтитул.

Пользователи @ Vitali-Kushner и @ mark-bessey сообщили об успехе даже с усеченными файлами, поэтому нижний колонтитул gzip не кажется строго обязательным.

@ tobias-kienzler предложил эту функцию для :
zlipd() (printf "\x1f\x8b\x08\x00\x00\x00\x00\x00" |cat - $@ |gzip -dc)

wkpark
источник
gzip не работает, но zlib-flate работает (поток содержимого страницы pdf).
Даниэль С. Яицков,
70

Пользователь @tino прокомментировал ниже ответ OpenSSL, но я думаю, что это должно быть отдельным:

zlib-flate -uncompress < FILE

Я попробовал это, и это сработало для меня.

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

Catskul
источник
3
В отличие от других ответов, этот работает на OS X.
polym
2
@polym, как вы zlib-flate установили на MacOS? Я этого нигде не вижу.
Wildcard
4
@Wildcard извините за поздний ответ. Я думаю, что это пришло с qpdfпакетом, который я установил, brewкак упомянуто в комментарии выше - или посмотрите на последнее предложение этого ответа :). Кроме того, qpdfэто действительно круто, так что посмотрите на это тоже, если у вас есть время!
полим
brew install qpdf, затем команда, указанная выше :-) спасибо!
Фернандо Габриэли
60

Я нашел решение (одно из возможных), оно использует openssl :

$ openssl zlib -d < /tmp/data

или же

$ openssl zlib -d -in /tmp/data

* ПРИМЕЧАНИЕ: функциональность zlib, по-видимому, доступна в последних версиях openssl> = 1.0.0 (OpenSSL должен быть настроен / собран с опцией zlib или zlib-dynamic, последняя используется по умолчанию)

mykhal
источник
25
На Debian Squeeze (который имеет OpenSSL 0.9.8) есть zlib-flateв qpdfпакете. Это можно использовать как zlib-flate -uncompress < FILE.
Тино
7
zlib был удален из последних версий OpenSSL, так что этот совет очень полезен @Tino
Александр Курилин
1
Благодарю. Это решение обеспечивает лучший способ распаковки коротких входных файлов, чем ответ, используя «gzip» («openssl» распаковывает столько, сколько может, в то время как «gzip» прерывает печать «неожиданный конец файла»).
Даниэль К.
2
@ Тино, это должен быть отдельный ответ
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.

Предполагая файл с именем «тест»:

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

На OSX вы можете выполнить brew install pigz

snodnipper
источник
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
harpyon, я могу их распаковать, мне просто интересно, какие менее или более распространенные настройки urility или 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? Как так?
К.-Майкл Ай
Нету не работает для меня даже с поддельным заголовком.
Кибернард
3

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

Хенно Брандсма
источник
2

В macOS, которая полностью совместима с POSIX, 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;
Mecki
источник
1

Вы можете использовать это для сжатия с помощью zlib:

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
К.-Майкл Ай
-3
zcat -f infile > outfile 

у меня работает на fedora25

SIGXCPU
источник
1
zcatработает только с файлами в формате gzip.
Энтони