Как распаковать данные 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?


Здесь можно найти много дополнительных ответов: 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)


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

70

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

zlib-flate -uncompress < FILE

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

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


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, последняя используется по умолчанию)


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


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;

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


1
zcatработает только с файлами в формате gzip.
Энтони
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.