Вопрос: Почему Zip может сжимать один файл меньше, чем несколько файлов с тем же содержимым?


Предположим, что у меня есть 10 000 XML-файлов. Теперь предположим, что я хочу отправить их другу. Прежде чем отправлять их, я хотел бы сжать их.

Способ 1: не сжимайте их

Результаты:

Resulting Size: 62 MB
Percent of initial size: 100%

Способ 2. Запишите все файлы и отправьте ему 10 000 xml файлов

Команда:

for x in $(ls -1) ;  do   echo $x ; zip "$x.zip" $x ; done

Результаты:

Resulting Size: 13 MB
Percent of initial size: 20%

Способ 3. Создайте один почтовый индекс, содержащий 10 000 xml-файлов

Команда:

zip all.zip $(ls -1)

Результаты:

Resulting Size: 12 MB
Percent of initial size: 19%

Способ 4: объединить файлы в один файл и закрепить его

Команда:

cat *.xml > oneFile.txt ; zip oneFile.zip oneFile.txt

Результаты:

Resulting Size: 2 MB
Percent of initial size: 3%

Вопросов:

  • Почему я получаю такие потрясающе лучшие результаты, когда я просто зажимаю один файл?
  • Я ожидал получить значительно лучшие результаты, используя метод 3, чем метод 2, но не буду. Зачем?
  • Является ли это поведение специфичным для zip? Если я попытался использовать gzip я получаю разные результаты?

Дополнительная информация:

$ zip --version
Copyright (c) 1990-2008 Info-ZIP - Type 'zip "-L"' for software license.
This is Zip 3.0 (July 5th 2008), by Info-ZIP.
Currently maintained by E. Gordon.  Please send bug reports to
the authors using the web page at www.info-zip.org; see README for details.

Latest sources and executables are at ftp://ftp.info-zip.org/pub/infozip,
as of above date; see http://www.info-zip.org/ for other sites.

Compiled with gcc 4.4.4 20100525 (Red Hat 4.4.4-5) for Unix (Linux ELF) on Nov 11 2010.

Zip special compilation options:
    USE_EF_UT_TIME       (store Universal Time)
    SYMLINK_SUPPORT      (symbolic links supported)
    LARGE_FILE_SUPPORT   (can read and write large files on file system)
    ZIP64_SUPPORT        (use Zip64 to store large files in archives)
    UNICODE_SUPPORT      (store and read UTF-8 Unicode paths)
    STORE_UNIX_UIDs_GIDs (store UID/GID sizes/values using new extra field)
    UIDGID_NOT_16BIT     (old Unix 16-bit UID/GID extra field not used)
    [encryption, version 2.91 of 05 Jan 2007] (modified for Zip 3)

Изменить: Метаданные

Один ответ предполагает, что разница в метаданных системы, которая хранится в zip. Я не думаю, что это может быть так. Чтобы проверить, я сделал следующее:

for x in $(seq 10000) ; do touch $x ; done
zip allZip $(ls -1)

Получаемый zip составляет 1,4 МБ. Это означает, что все еще существует ~ 10 МБ необъяснимого пространства.


119
2017-12-14 17:30


Источник


Если я не ошибаюсь, именно эта феномона заставляет людей .tar.gz в отличие от простого копирования всего каталога. - corsiKa
аналогичный вопрос был уже задан, tl; dr использует твердые архивы 7zip. - Dmitry Grigoryev
@sixtyfootersdude Как тест для проверки некоторых ответов, можете ли вы попробовать zip zip, созданный в методе 3? Я подозреваю, что это уменьшит размер файла до уровня, сравнимого с методом 4. - Travis
Вместо $(ls -1), просто используйте *: for x in *; zip all.zip * - muru
Если вы хотите сделать сплошное сжатие с помощью ZIP, обходным путем: во-первых, создайте несжатый ZIP, содержащий все ваши файлы. Затем поместите этот ZIP в другой сжатый ZIP. - user20574


Ответы:


Zip обрабатывает содержимое каждого файла отдельно при сжатии. Каждый файл будет иметь собственный сжатый поток. Существует поддержка в рамках алгоритма сжатия (обычно DEFLATE) для идентификации повторяющихся разделов. Однако в Zip нет поддержки для поиска избыточности между файлами.

Вот почему есть много лишнего места, когда содержимое находится в нескольких файлах: он ставит один и тот же сжатый поток в файл несколько раз.


124
2017-12-14 19:24



Кроме того, некоторые инструменты сжатия дают вам возможность сжимать файлы отдельно или как единый объект. (Хотя обычно это также означает, что вам нужно распаковать больше архива, чем в противном случае, если вы хотите просмотреть только один файл в нем.) - JAB
@JAB: Компрессионные инструменты, такие как 7z и rar, используют термин «твердый» архив для упаковки нескольких файлов в хвост в более крупные потоки сжатия. При умеренном размере фрагмента, таком как 64MiB, произвольный доступ к одному файлу может потребовать декомпрессии до 64 Мбайт данных с самого начала блока сжатия, в котором он находится. Вы можете получить достойный компромисс между случайным доступом и поиском избыточного количества файлов. 7z может использовать более эффективную (но более медленную для сжатия) схему сжатия LZMA, что является еще одним преимуществом по сравнению с zip. - Peter Cordes
Вы говорите, что there is no support in Zip to find redundancy between files находится в спецификации zip-файла? - sixtyfootersdude
@sixtyfootersdude Многие алгоритмы сжатия, такие как DEFLATE, работают как поток. Чтобы восстановить достаточную информацию для распаковки части потока, вам необходимо обработать весь поток до этой точки. Если они попытались найти избыточность между файлами, вам придется распаковать все 1000 файлов, чтобы добраться до последнего. Это, как правило, работает tgz. Однако zip был разработан, чтобы вы могли извлекать отдельные файлы. tgz предназначен для того, чтобы быть более или все-ничего - Cort Ammon
@sixtyfootersdude - это правильно. Перефразировать Cort: спецификации pkzip не поддерживают рабочий файл. Если бы они сделали, то для извлечения одного файла может потребоваться извлечение всего архива (и каждого файла). - James Snell


ZIP-сжатие основано на повторяющихся шаблонах в сжатых данных, и сжатие становится лучше, чем дольше файл, так как можно найти и использовать все больше и больше шаблонов.

Упрощенный, если вы сжимаете один файл, словарь, который отображает (короткие) коды на (более длинные) шаблоны, обязательно содержится в каждом результирующем zip-файле; если вы застегиваете один длинный файл, словарь «повторно используется» и становится еще более эффективным для всего контента.

Если ваши файлы даже немного похожи (так как текст всегда есть), повторное использование словаря становится очень эффективным, а результат - намного меньшим общим zip.


46
2017-12-14 18:48



ZIP выполняет как архивирование, так и сжатие. Означает ли это, что ZIP сжимает каждый файл по отдельности, даже если все они попадают в один ZIP-файл? - gerrit
это должно быть - представьте, что вы удаляете один файл, вы не хотите, чтобы он потратил еще полчаса на повторное сжатие остальных с помощью нового словаря. - также, вероятно, предполагается, что разные файлы нуждаются в очень разных словарях. - Aganju
Я не понимаю, зачем это нужно. С инструментами Unix я бы сначала архивировал файл с tar, а затем сжимал его с помощью gzip / bz2 / lzma. Алгоритму сжатия все равно, сколько файлов закодировано в архиве. Кроме того, насколько распространено удаление одного файла из сжатого архива? Я не думаю, что когда-либо это делал. - gerrit
Я не согласен, и это, наверное, хороший способ. Я не проектировал и не писал ZIP. Я просто сказал, что он делает ... - Aganju
@gerrit У этого есть свои проблемы. Zip предназначен для быстрого доступа к любому файлу в архиве - попробуйте распаковать один файл из архива UHA размером 100 гигабайт, и вы поймете, почему они выбрали этот путь. Он также предназначен для добавления - вы можете создать резервную копию и просто добавлять (или заменять) файлы по мере необходимости. Все это огромная помощь при использовании архивов. Компромисс заключается в том, что если вы сжимаете файлы, которые очень похожи (что не все это общее), он не может использовать сходства для уменьшения размера архива. - Luaan


В Zip каждый файл сжимается отдельно. Противоположность - «твердое сжатие», то есть файлы сжимаются вместе. 7-zip и Rar используют сплошное сжатие по умолчанию. Gzip и Bzip2 не могут сжимать несколько файлов, поэтому сначала используется Tar, с тем же эффектом, что и сплошное сжатие.

Поскольку файл xml имеет схожую структуру и, возможно, аналогичный контент, если файлы сжаты вместе, сжатие будет выше.

Например, если файл содержит строку "<content><element name=" и компрессор уже обнаружил, что строка в другом файле заменит его небольшим указателем на предыдущее совпадение, если компрессор не использует «сплошное сжатие», первое вхождение строки в файл будет записано как литерал, который больше.


42
2017-12-14 20:02





Zip не просто сохраняет содержимое файла, он также сохраняет метаданные файлов, такие как идентификатор пользователя, разрешения, время создания и модификации и т. Д. Если у вас есть один файл, у вас есть один набор метаданных; если у вас есть 10 000 файлов, у вас есть 10 000 наборов метаданных.


9
2017-12-14 17:38



Хорошая точка, но метаданные системы просто занимают 1,4 МБ пространства. См. Мое редактирование. - sixtyfootersdude
Я не знаком с алгоритмом zip, но метаданные - это не только информация о файле, но также такие вещи, как размер и словарь, возможно, некоторая информация о распределении символов. Словарь в непустом текстовом файле будет отличным от нуля. Вероятно, поэтому вы видите, что метаданные больше в ваших xml-файлах, чем ваши пустые файлы. - Ben Richards
Это была моя первая мысль. Информация заголовка Zip-файла - WernerCD
Это объясняет только разницу между 2 и 3 - не 4. - Luaan
@Luaan Нет, в обоих случаях 2 и 3 метаданные для всех 10 000 файлов включены в zip-файл или файлы, поэтому общий размер файла почти такого же размера. В 4 есть только метаданные для одного файла, а zip-файл намного меньше. - Mike Scott


Опция, пропущенная OP, заключается в том, чтобы закрепить все файлы вместе с отключенным сжатием, а затем закрепить полученный zip с максимальным сжатием. Это примерно эмулирует поведение сжатых архивов * nix .tar.Z, .tar.gz, .tar.bz и т. Д., Позволяя сжатию использовать избыточность между границами файлов (которые алгоритм ZIP не может выполнять при запуске в одном проходить). Это позволяет впоследствии извлекать отдельные файлы XML, но максимизирует сжатие. Недостатком является то, что для процесса извлечения требуется дополнительный шаг, временно использующий гораздо больше дискового пространства, чем это необходимо для обычного .zip.

С распространением бесплатных инструментов, таких как 7-Zip, чтобы расширить семейство tar до Windows, нет оснований не использовать файлы .tar.gz или .tar.bz и т. Д., Так как Linux, OS X и BSD имеют все нативные инструменты для их манипулирования.


6
2017-12-15 15:50



gzip и bzip2 могут оказаться еще хуже, потому что они разработаны с учетом сжатия потоков, поэтому им придется начинать вывод сжатых данных, прежде чем все данные для сжатия будут известны. - rackandboneman
@rackandboneman: Это компромисс, который вы должны выполнить при сжатии файлов, превышающих объем памяти, который вы хотите использовать во время сжатия. (И также, количество процессорного времени, необходимого для поиска чего-либо глобально оптимального, было бы огромным.) Огромный словарь сжатия также может увеличить объем памяти, необходимый для декомпрессия, Это вариант для LZMA (xz / 7-zip). Во всяком случае, адаптивные словари могут подбирать шаблоны, как только они будут видны. Не похоже, что он просто создает статическую систему кодирования, основанную на первых 32k. Вот почему gzip не сосать. - Peter Cordes


Формат сжатия zip хранит и сжимает каждый файл отдельно. Он не использует повторение между файлами, только внутри файла.

Объединение файла позволяет zip использовать повторения во всех файлах, что приводит к значительно большему сжатию.

Например, скажем, что каждый файл XML имеет определенный заголовок. Этот заголовок встречается только один раз в каждом файле, но повторяется почти одинаково во многих других файлах. В методах 2 и 3 zip не мог сжать для этого, но в методе 4 он мог бы.


5
2017-12-15 01:19



Как это отличается от одного из трех лучших ответов, уже опубликованных в 5 часов раньше? - Xen2050
@ Xen2050 Не большая разница, я просто подумал, что могу объяснить это более четко. - BonsaiOak
@BonsaiOak - добавьте комментарий к правильному ответу или отредактируйте, если у вас достаточно репутации. Если нет, но ваш комментарий добавляет ясности, кто-то другой может забрать это и отредактировать сообщение в любом случае. - AdamV
@AdamV Я вижу вашу мысль. Мой ответ в настоящее время не добавляет никакой полезной информации, хотя это, возможно, было, когда я это написал. В первом ответе уже есть соответствующие комментарии, поэтому я не вижу смысла добавлять их. Вы говорите, что я должен просто закрыть свой ответ? Какой вред он оставляет? - BonsaiOak


Рядом с метаданными Майк Скотт упомянул, что в алгоритме сжатия также есть накладные расходы.

При сжатии кучи отдельных небольших файлов вам будет очень повезло, что вы сможете сжать их, чтобы просто заполнить один блок сжатия. При сжатии одного монолитного блока система может просто продолжать передавать данные в свой алгоритм, игнорируя «границы» (из-за отсутствия лучшего слова) отдельных файлов.

Известно, что ASCII имеет высокий коэффициент сжатия. плюс xml часто очень повторяется, делая метаданные большим количеством данных, которые не могут быть так легко сжаты, как xml-контент.

Наконец, если память правильная, zip использует что-то вроде словарного кодирования, что особенно эффективно для файлов ascii и, тем более, для XML из-за их повторения

Объяснение сжатия данных: http://mattmahoney.net/dc/dce.html


4
2017-12-14 18:02