Warum kann Zip eine einzelne Datei kleiner als mehrere Dateien mit demselben Inhalt komprimieren?

126

Angenommen, ich habe 10.000 XML-Dateien. Angenommen, ich möchte sie an einen Freund senden. Bevor ich sie abschicke, möchte ich sie komprimieren.

Methode 1: Komprimieren Sie sie nicht

Ergebnisse:

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

Methode 2: Packen Sie jede Datei und senden Sie ihm 10.000 xml-Dateien

Befehl:

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

Ergebnisse:

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

Methode 3: Erstellen Sie eine einzelne Zip-Datei mit 10.000 XML-Dateien

Befehl:

zip all.zip $(ls -1)

Ergebnisse:

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

Methode 4: Verknüpfen Sie die Dateien zu einer einzigen Datei und komprimieren Sie sie

Befehl:

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

Ergebnisse:

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

Fragen:

  • Warum erhalte ich so dramatisch bessere Ergebnisse, wenn ich nur eine einzelne Datei komprimiere?
  • Ich hatte erwartet, mit Methode 3 drastisch bessere Ergebnisse zu erzielen als mit Methode 2, aber nicht. Warum?
  • Ist dieses Verhalten spezifisch für zip? Wenn ich es versuchen gzipwürde , würde ich unterschiedliche Ergebnisse erhalten?

Zusätzliche Information:

$ 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)

Bearbeiten: Metadaten

Eine Antwort legt nahe, dass der Unterschied in den im Zip gespeicherten System-Metadaten besteht. Ich denke nicht, dass dies der Fall sein kann. Zum Testen habe ich folgendes gemacht:

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

Die resultierende Zip ist 1.4MB. Dies bedeutet, dass noch ~ 10 MB unerklärlicher Speicherplatz vorhanden sind.

Sixtyfootersdude
quelle
34
Wenn ich mich nicht irre, ist es dieses Phänomen, das die Leute dazu bringt, etwas zu machen .tar.gz, anstatt nur das ganze Verzeichnis zu zippen.
corsiKa
18
Eine ähnliche Frage wurde bereits gestellt: Verwenden Sie solide 7zip-Archive.
Dmitry Grigoryev
3
@sixtyfootersdude Können Sie als Test zur Überprüfung einiger Antworten versuchen, die in Methode 3 erstellte Zip-Datei zu komprimieren? Ich vermute, dass dies die Dateigröße auf etwas reduziert, das mit Methode 4 vergleichbar ist.
Travis
7
Statt $(ls -1), benutzen Sie einfach *: for x in *; zip all.zip *
Muru
4
Wenn Sie eine solide Komprimierung mit ZIP durchführen möchten, können Sie dies folgendermaßen umgehen: Erstellen Sie zunächst eine nicht komprimierte ZIP-Datei, die alle Ihre Dateien enthält. Legen Sie diese ZIP-Datei dann in eine andere komprimierte ZIP-Datei.
user20574

Antworten:

129

Zip behandelt den Inhalt jeder Datei beim Komprimieren separat. Jede Datei hat einen eigenen komprimierten Stream. Der Komprimierungsalgorithmus (normalerweise DEFLATE ) unterstützt das Identifizieren von wiederholten Abschnitten. Zip bietet jedoch keine Unterstützung für das Auffinden von Redundanz zwischen Dateien.

Das ist der Grund, warum es so viel zusätzlichen Speicherplatz gibt, wenn sich der Inhalt in mehreren Dateien befindet: Es wird derselbe komprimierte Stream mehrmals in die Datei eingefügt.

Alan Shutko
quelle
9
Einige Komprimierungswerkzeuge bieten Ihnen auch die Möglichkeit, die Dateien einzeln oder als einzelne Einheit zu komprimieren. (Im Allgemeinen bedeutet dies jedoch auch, dass Sie mehr Archivdateien dekomprimieren müssen als sonst, wenn Sie nur eine einzelne Datei darin anzeigen möchten.)
JAB
28
@JAB: Komprimierungstools wie 7z und rar verwenden den Begriff "solides" Archiv, um mehrere Dateien von Kopf bis Fuß in größere Komprimierungsströme zu packen. Bei einer moderaten Blockgröße von 64 MB ist für den wahlfreien Zugriff auf eine einzelne Datei möglicherweise eine Dekomprimierung von bis zu 64 MB Daten ab dem Beginn des Komprimierungsblocks erforderlich. Sie können einen angemessenen Kompromiss zwischen wahlfreiem Zugriff und der Suche nach dateiübergreifender Redundanz erzielen. 7z kann das effektivere (aber langsamer zu komprimierende) LZMA-Komprimierungsschema verwenden, was ein weiterer Vorteil gegenüber zip ist.
Peter Cordes
Wollen Sie damit sagen, dass dies there is no support in Zip to find redundancy between filesin der Zip-Dateispezifikation steht?
Sixtyfootersdude
6
@sixtyfootersdude Viele Komprimierungsalgorithmen wie DEFLATE arbeiten als Stream. Um genügend Informationen zum Dekomprimieren eines Teils des Streams wiederherzustellen, müssen Sie den gesamten Stream bis zu diesem Zeitpunkt verarbeiten. Wenn sie versuchen, die Redundanz zwischen Dateien zu finden, müssen Sie alle 1000 Dateien dekomprimieren, um zur letzten zu gelangen. Dies ist in der Regel, wie Tgz tatsächlich funktioniert. Mit zip können Sie jedoch einzelne Dateien extrahieren. tgz soll mehr Alles oder Nichts sein
Cort Ammon
1
@sixtyfootersdude - das stimmt. Um Cort zu paraphrasieren: Die pkzip-Spezifikationen unterstützen das dateiübergreifende Arbeiten nicht. Wenn dies der Fall wäre, müsste beim Extrahieren einer Datei möglicherweise das gesamte Archiv (und jede Datei) extrahiert werden.
James Snell
48

Die ZIP-Komprimierung basiert auf sich wiederholenden Mustern in den zu komprimierenden Daten, und die Komprimierung wird umso besser, je länger die Datei ist, je mehr und längere Muster gefunden und verwendet werden können.

Vereinfacht ausgedrückt, wenn Sie eine Datei komprimieren, ist das Wörterbuch, das (kurze) Codes (längeren) Mustern zuordnet, notwendigerweise in jeder resultierenden Zip-Datei enthalten. Wenn Sie eine lange Datei komprimieren, wird das Wörterbuch wieder verwendet und wirkt sich auf den gesamten Inhalt aus.

Wenn Ihre Dateien sogar ein bisschen ähnlich sind (wie es Text immer ist), wird die Wiederverwendung des 'Wörterbuchs' sehr effizient und das Ergebnis ist eine viel kleinere Gesamt-Zip.

Aganju
quelle
3
ZIP archiviert und komprimiert. Bedeutet das, dass ZIP jede Datei einzeln komprimiert, auch wenn sie alle in derselben ZIP-Datei landen?
Gerrit
2
Das muss so sein - stellen Sie sich vor, Sie entfernen eine einzelne Datei und möchten nicht, dass sie eine weitere halbe Stunde benötigt, um den Rest mit einem neuen "Wörterbuch" neu zu komprimieren. - Vermutlich wird davon ausgegangen, dass verschiedene Dateien sehr unterschiedliche "Wörterbücher" benötigen.
Aganju
2
Ich verstehe nicht, warum es muss. Mit Unix-Tools würde ich zuerst eine Datei mit tar archivieren und dann mit gzip / bz2 / lzma komprimieren. Dem Komprimierungsalgorithmus ist es egal, wie viele Dateien im Archiv codiert sind. Wie häufig wird eine einzelne Datei tatsächlich aus einem komprimierten Archiv entfernt? Ich glaube nicht, dass ich das jemals getan habe.
Gerrit
4
Ich bin nicht anderer Meinung, und das ist wahrscheinlich ein guter Weg. Ich habe kein ZIP entworfen oder geschrieben. Ich habe gerade gesagt, was es tut ...
Aganju
16
@ Gerrit Es hat seine eigenen Probleme. Mit Zip können Sie schnell auf alle Dateien im Archiv zugreifen. Versuchen Sie, eine einzelne Datei aus einem 100-GiB-UHA-Archiv zu entpacken, und Sie werden sehen, warum diese Dateien ausgewählt wurden. Es kann auch angehängt werden - Sie können Ihre Backup-Zip-Datei haben und einfach nach Bedarf weitere Dateien hinzufügen (oder ersetzen). All dies ist eine große Hilfe bei der Verwendung von Archiven. Der Nachteil ist, dass beim Komprimieren sehr ähnlicher Dateien (was nicht allzu häufig vorkommt) die Ähnlichkeiten nicht ausgenutzt werden können, um die Archivgröße zu reduzieren.
Luaan
43

In Zip wird jede Datei separat komprimiert. Das Gegenteil ist "solide Komprimierung", dh Dateien werden zusammen komprimiert. 7-zip und Rar verwenden standardmäßig eine solide Komprimierung. Gzip und Bzip2 können nicht mehrere Dateien komprimieren, daher wird zuerst Tar verwendet. Dies hat den gleichen Effekt wie eine solide Komprimierung.

Da die XML-Datei eine ähnliche Struktur und wahrscheinlich einen ähnlichen Inhalt hat, wenn die Dateien zusammen komprimiert werden, ist die Komprimierung höher.

Wenn beispielsweise eine Datei die Zeichenfolge enthält "<content><element name="und der Komprimierer diese Zeichenfolge bereits in einer anderen Datei gefunden hat, wird sie durch einen kleinen Zeiger auf die vorherige Übereinstimmung ersetzt, wenn der Komprimierer beim ersten Auftreten der Zeichenfolge in der nicht die Option "Feste Komprimierung" verwendet Die Datei wird als Literal aufgezeichnet, das größer ist.

ggf31416
quelle
9

Zip speichert nicht nur den Inhalt der Datei, sondern auch Dateimetadaten wie die Benutzer-ID, Berechtigungen, Erstellungs- und Änderungszeiten usw. Wenn Sie eine Datei haben, haben Sie einen Metadatensatz. Wenn Sie 10.000 Dateien haben, haben Sie 10.000 Metadatensätze.

Mike Scott
quelle
3
Guter Punkt, aber die System-Metadaten belegen nur 1,4 MB Speicherplatz. Siehe meine Bearbeitung.
Sixtyfootersdude
1
Ich bin nicht mit dem Zip-Algorithmus vertraut, aber die Metadaten sind nicht nur die Dateiinformationen, sondern auch Dinge wie Größe und ein Wörterbuch, möglicherweise einige Informationen zur Verteilung von Zeichen. Ein Wörterbuch in einer nicht leeren Textdatei ist ungleich Null. Wahrscheinlich sehen Sie deshalb, dass die Metadaten in Ihren XML-Dateien größer sind als in Ihren leeren Dateien.
Ben Richards
Das war mein erster Gedanke. Informationen zum Zip-File-Header
WernerCD
Dies erklärt nur den Unterschied zwischen 2 und 3 - nicht 4.
Luaan
@Luaan Nein, sowohl in 2 als auch in 3 sind die Metadaten für alle 10.000 Dateien in der ZIP-Datei oder den ZIP-Dateien enthalten, sodass die Gesamtgröße der Dateien nahezu gleich ist. In 4 gibt es nur Metadaten für eine Datei, und die ZIP-Datei ist viel kleiner.
Mike Scott
7

Eine vom OP verpasste Option besteht darin, alle Dateien zusammen mit deaktivierter Komprimierung zu komprimieren und dann die resultierende ZIP-Datei mit maximaler Komprimierung zu komprimieren. Dies emuliert in etwa das Verhalten von komprimierten * nix .tar.Z-, .tar.gz-, .tar.bz- usw. Archiven, indem die Komprimierung Redundanzen über Dateigrenzen hinweg ausnutzt (was der ZIP-Algorithmus nicht kann, wenn er in einem einzigen Archiv ausgeführt wird bestehen). Dies ermöglicht das spätere Extrahieren der einzelnen XML-Dateien, maximiert jedoch die Komprimierung. Der Nachteil ist, dass für den Extraktionsprozess ein zusätzlicher Schritt erforderlich ist und vorübergehend viel mehr Speicherplatz benötigt wird, als für ein normales ZIP-Archiv erforderlich wäre.

Mit der Allgegenwart kostenloser Tools wie 7-Zip zur Erweiterung der Tar-Familie auf Windows gibt es wirklich keinen Grund, auf die Verwendung von .tar.gz oder .tar.bz usw. zu verzichten, wie dies bei Linux, OS X und allen BSDs der Fall ist native Tools, um sie zu manipulieren.

Monty Harder
quelle
gzip und bzip2 könnten sogar noch schlimmer werden, da sie für die Komprimierung von Streams entwickelt wurden. Daher müssen sie erst komprimierte Daten ausgeben, bevor alle zu komprimierenden Daten überhaupt bekannt sind.
Rackandboneman
@rackandboneman: Dies ist der Kompromiss, den Sie eingehen müssen, wenn Sie Dateien komprimieren, die größer sind als der Speicher, den Sie zur Komprimierungszeit verwenden möchten. (Außerdem wäre die CPU-Zeit, die erforderlich ist, um global optimale Ergebnisse zu erzielen, enorm.) Ein umfangreiches Komprimierungswörterbuch kann auch den für die Dekomprimierung erforderlichen Speicher erhöhen . Dies ist eine Option für LZMA ( xz/ 7-zip). Wie auch immer, adaptive Wörterbücher können Muster erkennen, sobald sie sichtbar sind. Es ist nicht so, dass es nur ein statisches Codierungssystem auf der Basis der ersten 32 KB erstellt. Deshalb saugt gzip nicht.
Peter Cordes
Ich mag diesen "Trick" wirklich, wenn Sie beim Zip-Format bleiben müssen. Ich bin nicht einverstanden mit Ihrem "Kein Grund, 7-zip nicht zu verwenden" - wenn ich eine Datei an einen nicht-technischen Freund sende, möchte ich sicher sein, dass er sie problemlos öffnen kann. Wenn ich an einen Geschäftskunden sende, umso mehr.
Wowfunhappy
5

Das Zip-Komprimierungsformat speichert und komprimiert jede Datei separat. Die Wiederholung zwischen Dateien wird nicht ausgenutzt, sondern nur innerhalb einer Datei.

Durch die Verkettung der Datei kann zip die Wiederholungen aller Dateien nutzen, was zu einer drastisch höheren Komprimierung führt.

Angenommen, jede XML-Datei hat einen bestimmten Header. Dieser Header kommt in jeder Datei nur einmal vor, wird jedoch in vielen anderen Dateien fast identisch wiederholt. In Methode 2 und 3 konnte zip dies nicht komprimieren, in Methode 4 jedoch.

BonsaiOak
quelle
3
Inwiefern unterscheidet sich diese Antwort von einer der Top-3-Antworten, die bereits 5 Stunden zuvor veröffentlicht wurden?
Xen2050
1
@ Xen2050 Kein großer Unterschied, ich dachte nur, ich könnte es klarer erklären.
BonsaiOak
1
@BonsaiOak - dann füge einen Kommentar zur richtigen Antwort hinzu oder bearbeite sie, wenn du genug Repräsentanten hast. Wenn nicht, aber Ihr Kommentar erhöht die Klarheit, könnte jemand anderes dies aufgreifen und den Beitrag trotzdem bearbeiten.
AdamV
@AdamV Ich verstehe deinen Standpunkt. Meine Antwort fügt derzeit keine nützlichen Informationen hinzu, obwohl dies wohl der Fall war, als ich sie schrieb. Die erste Antwort enthält bereits entsprechende Kommentare, daher sehe ich auch keinen Sinn darin, sie hinzuzufügen. Wollen Sie damit sagen, dass ich nur meine Antwort schließen soll? Was schadet es, es offen zu lassen?
BonsaiOak
4

Neben den Metadaten, die Mike Scott erwähnte, gibt es auch Overhead im Komprimierungsalgorithmus.

Wenn Sie eine Reihe kleiner Dateien komprimieren, müssen Sie das große Glück haben, sie komprimieren zu können, da sie zufällig nur einen Komprimierungsblock füllen. Wenn ein einzelner monolithischer Block komprimiert wird, kann das System einfach den Datenstrom zu seinem Algorithmus fortsetzen, wobei die "Grenzen" (mangels besserer Worte) der einzelnen Dateien ignoriert werden.

Es ist auch bekannt, dass ASCII einen hohen Komprimierungsfaktor aufweist. plus xml wiederholt sich oft sehr oft und macht die Metadaten zu einem großen Teil der Daten, die nicht so einfach komprimiert werden können wie der xml-Inhalt.

Wenn der Speicher richtig belegt ist, verwendet zip eine Art Wörterbuchcodierung, die sich aufgrund ihrer Wiederholbarkeit besonders auf ASCII-Dateien und insbesondere auf XML auswirkt

Erklärung der Datenkomprimierung: http://mattmahoney.net/dc/dce.html

GapWim
quelle
3

Betrachten Sie diese XML:

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

Eine XML hat eine sehr sich wiederholende Struktur. Zip nutzt diese Wiederholungen, um ein Wörterbuch zu erstellen, dessen Muster häufiger vorkommt, und verwendet dann beim Komprimieren weniger Bits, um mehr sich wiederholende Muster und mehr Bits, um weniger sich wiederholende Muster zu speichern .

Wenn Sie diese Dateien verketten , ist die Quelldatei (die Quelle für zip) groß, enthält jedoch viel mehr sich wiederholende Muster, da die Verteilung der langweiligen Strukturen eines XML in der großen gesamten Datei amortisiert wird und ZIP die Möglichkeit bietet, diese Muster zu speichern mit weniger Bits.

Wenn Sie nun verschiedene XML-Dateien in einer einzigen Datei kombinieren, findet der Komprimierungsalgorithmus die beste Musterverteilung über alle Dateien und nicht Datei für Datei.

Letztendlich hat der Komprimierungsalgorithmus die beste wiederholte Musterverteilung gefunden.

rnrneverdies
quelle
-1

Zusätzlich zur 7-Zip-Antwort gibt es einen anderen Ansatz, der nicht so gut ist, aber einen Test wert wäre, wenn Sie 7-Zip aus irgendeinem Grund nicht verwenden möchten:

Komprimieren Sie die Zip-Datei. Normalerweise ist eine Zip-Datei inkomprimierbar. Wenn sie jedoch viele identische Dateien enthält, kann der Kompressor diese Redundanz finden und komprimieren. Beachten Sie, dass ich auch einen kleinen Gewinn gesehen habe, wenn ich mit einer großen Anzahl von Dateien ohne Redundanz umgegangen bin. Wenn Sie sich wirklich für die Größe interessieren, lohnt es sich, es zu versuchen, wenn Sie sehr viele Dateien in Ihrer Zip-Datei haben.

Loren Pechtel
quelle
Das funktioniert nur, wenn Sie den ersten Reißverschluss mit deaktivierter Komprimierung machen, wie oben erwähnt.
Monty Harder
@MontyHarder Ich habe gesehen, wie es mit aktivierter Komprimierung funktioniert.
Loren Pechtel