121

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

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

Результаты:

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

Способ 2: архивировать каждый файл и отправить ему 10000 XML-файлов

Команда:

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

Результаты:

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

Способ 3: создать один ZIP-файл, содержащий 10000 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)

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

9 ответов9

126

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

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

47

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

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

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

42

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

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

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

9

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

6

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

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

5

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

Конкатенация файлов позволяет zip использовать преимущества повторений для всех файлов, что приводит к значительному увеличению сжатия.

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

4

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

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

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

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

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

3

Рассмотрим этот XML:

<root>
  <element id="1" />
  <element id="2" /> 
  <other id="3" />
  ...
</root>

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

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

Теперь, если вы объединяете разные XML в один файл, даже если эти файлы имеют совершенно разные имена тегов, алгоритм сжатия найдет наилучшее распределение шаблонов по всем файлам, а не файл за файлом.

В конечном итоге алгоритм сжатия нашел наилучшее повторное распределение паттернов.

-1

В дополнение к ответу 7-Zip есть еще один подход, который не так хорош, но стоит попробовать, если по какой-то причине вы не хотите использовать 7-Zip:

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

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .