Pourquoi Zip peut-il compresser un fichier plus petit que plusieurs fichiers ayant le même contenu?

126

Supposons que j'ai 10 000 fichiers XML. Supposons maintenant que je veuille les envoyer à un ami. Avant de les envoyer, je voudrais les compresser.

Méthode 1: ne les compressez pas

Résultats:

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

Méthode 2: Zip chaque fichier et lui envoyer 10 000 fichiers xml

Commander:

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

Résultats:

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

Méthode 3: créer un zip unique contenant 10 000 fichiers XML

Commander:

zip all.zip $(ls -1)

Résultats:

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

Méthode 4: Concaténez les fichiers en un seul fichier et décompressez-le

Commander:

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

Résultats:

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

Des questions:

  • Pourquoi ai-je des résultats tellement meilleurs alors que je ne fais que compresser un fichier?
  • Je m'attendais à obtenir des résultats nettement meilleurs en utilisant la méthode 3 que la méthode 2, mais ce n'est pas le cas. Pourquoi?
  • Ce comportement est-il spécifique à zip? Si j'essayais d'utiliser, gzipobtiendrais-je des résultats différents?

Information additionnelle:

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

Edit: métadonnées

Une réponse suggère que la différence réside dans les métadonnées système stockées dans le zip. Je ne pense pas que cela puisse être le cas. Pour tester, j'ai fait ce qui suit:

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

Le zip résultant est de 1,4 Mo. Cela signifie qu’il reste environ 10 Mo d’espace inexpliqué.

soixantefootersdude
la source
34
Si je ne me trompe pas, c'est ce phénomène qui pousse les gens à faire .tar.gzopposition au simple fait de compresser tout le répertoire.
CorsiKa
18
Une question similaire avait déjà été posée, elle utilisait des archives solides 7zip.
Dmitry Grigoryev
3
@sixtyfootersdude Comme test pour valider certaines des réponses, pouvez-vous compresser le zip créé dans la méthode 3? Je pense que cela réduira la taille du fichier à un résultat comparable à celui de la méthode 4.
Travis
7
Au lieu de $(ls -1), il suffit d' utiliser *: for x in *; zip all.zip *
muru
4
Si vous souhaitez effectuer une compression solide avec ZIP, voici une solution de contournement: créez d’abord un ZIP non compressé contenant tous vos fichiers. Ensuite, mettez ce ZIP dans un autre ZIP compressé.
user20574

Réponses:

129

Zip traite le contenu de chaque fichier séparément lors de la compression. Chaque fichier aura son propre flux compressé. L'algorithme de compression (généralement DEFLATE ) permet d'identifier les sections répétées. Cependant, Zip ne prend pas en charge la recherche de redondance entre les fichiers.

C'est pourquoi il y a tellement d'espace supplémentaire lorsque le contenu se trouve dans plusieurs fichiers: cela place le même flux compressé dans le fichier plusieurs fois.

Alan Shutko
la source
9
C'est également pourquoi certains outils de compression vous offrent la possibilité de compresser les fichiers séparément ou en une seule entité. (Bien qu'en général, cela signifie également que vous devez décompresser davantage de l'archive que si vous ne vouliez afficher qu'un seul fichier.)
JAB
28
@JAB: Les outils de compression tels que 7z et rar utilisent le terme d'archives "solid" pour regrouper plusieurs fichiers en bout de ligne dans des flux de compression plus importants. Avec une taille de bloc modérée, telle que 64 Mo, un accès aléatoire à un fichier unique peut nécessiter la décompression de 64 Mo maximum de données à partir du début du bloc de compression dans lequel il se trouve. Vous pouvez obtenir un bon compromis entre accès aléatoire et recherche de la redondance entre fichiers. 7z peut utiliser le schéma de compression LZMA le plus efficace (mais le plus lent à compresser), ce qui constitue un autre avantage par rapport à zip.
Peter Cordes
Voulez-vous dire que cela se there is no support in Zip to find redundancy between filestrouve dans la spécification du fichier zip?
Sixtyfootersdude
6
@sixtyfootersdude De nombreux algorithmes de compression, tels que DEFLATE, fonctionnent en tant que flux. Pour récupérer suffisamment d'informations pour décompresser une partie du flux, vous devez traiter l'intégralité du flux jusqu'à ce point. S'ils essayaient de trouver la redondance entre les fichiers, vous deviez décompresser tous les 1000 fichiers pour accéder au dernier. C'est typiquement ainsi que fonctionne tgz. Cependant, zip a été conçu pour vous permettre d'extraire des fichiers individuels. tgz est conçu pour être plus ou presque
Cort Ammon
1
@stytyfootersdude - c'est correct. Pour paraphraser Cort: Les spécifications de pkzip ne permettent pas de travailler avec plusieurs fichiers. Si tel est le cas, l'extraction d'un fichier peut nécessiter l'extraction de l'archive complète (et de chaque fichier).
James Snell
48

La compression ZIP est basée sur des motifs répétitifs dans les données à compresser. Plus la taille du fichier est longue, plus la compression est longue, plus les motifs peuvent être trouvés et utilisés plus longtemps.

Simplifié, si vous compressez un fichier, le dictionnaire qui associe des codes (courts) à des modèles (plus longs) est nécessairement contenu dans chaque fichier zip résultant. Si vous zippez un fichier long, le dictionnaire est «réutilisé» et gagne en efficacité sur tous les contenus.

Si vos fichiers sont même un peu similaires (le texte l'est toujours), la réutilisation du dictionnaire devient très efficace et le résultat est un zip total beaucoup plus petit.

Aganju
la source
3
ZIP effectue à la fois l'archivage et la compression. Est-ce que cela signifie que ZIP compresse chaque fichier individuellement, même s'ils se retrouvent tous dans le même fichier ZIP?
gerrit
2
imaginez que vous supprimiez un seul fichier, vous ne voudriez pas qu'il passe encore une demi-heure à recomposer le reste avec un nouveau "dictionnaire". - de plus, cela suppose probablement que différents fichiers nécessitent des «dictionnaires» très différents.
Aganju
2
Je ne vois pas pourquoi. Avec les outils Unix, je commencerais par archiver un fichier avec tar, puis le compresser avec gzip / bz2 / lzma. L'algorithme de compression ne tient pas compte du nombre de fichiers encodés dans l'archive. En outre, à quel point est-il courant de supprimer un seul fichier d'une archive compressée? Je ne pense pas avoir déjà fait ça.
gerrit
4
Je ne suis pas en désaccord et c'est probablement un bon moyen. Je n'ai pas conçu ou écrit ZIP. Je viens de dire ce que ça fait ...
Aganju
16
@ gerrit Il a ses propres problèmes. Zip est conçu pour vous permettre d’accéder rapidement à n’importe quel fichier de l’archive. Essayez de décompresser un seul fichier à partir d’une archive de 100 Gio UHA et vous verrez pourquoi ils ont choisi cette méthode. Il est également conçu pour l’ajout. Vous pouvez avoir votre fichier compressé et continuer à ajouter (ou remplacer) des fichiers au besoin. Tout cela représente une aide considérable lors de l’utilisation des archives. Le compromis est que si vous compressez des fichiers très similaires (ce qui n'est pas si courant), il ne peut pas exploiter les similitudes pour réduire la taille de l'archive.
Luaan
43

Dans Zip, chaque fichier est compressé séparément. Le contraire est «compression solide», c'est-à-dire que les fichiers sont compressés ensemble. 7-zip et Rar utilisent la compression solide par défaut. Gzip et Bzip2 ne peuvent pas compresser plusieurs fichiers, donc Tar est utilisé en premier, ayant le même effet qu'une compression solide.

Comme le fichier XML a une structure similaire et probablement un contenu similaire, si les fichiers sont compressés ensemble, la compression sera plus élevée.

Par exemple, si un fichier contient la chaîne "<content><element name="et que le compresseur a déjà trouvé cette chaîne dans un autre fichier, il le remplacera par un petit pointeur sur la correspondance précédente. Le fichier sera enregistré comme un littéral plus volumineux.

ggf31416
la source
9

Zip ne stocke pas uniquement le contenu du fichier, il stocke également des métadonnées de fichier telles que l'ID utilisateur propriétaire, les autorisations, les temps de création et de modification, etc. Si vous avez un fichier, vous avez un ensemble de métadonnées; si vous avez 10 000 fichiers, vous avez 10 000 jeux de métadonnées.

Mike Scott
la source
3
Bon point, mais les métadonnées du système occupent tout juste 1,4 Mo d’espace. Voir mon édition.
sixtyfootersdude
1
Je ne suis pas familier avec l'algorithme zip, mais les métadonnées ne sont pas seulement des informations sur les fichiers, mais aussi des choses comme la taille et un dictionnaire, éventuellement des informations sur la distribution des caractères. Un dictionnaire sur un fichier texte non vide sera non nul. C'est probablement pour cette raison que vous voyez que les métadonnées sont plus grandes dans vos fichiers XML que dans vos fichiers vides.
Ben Richards
Il s'agissait de ma première pensée. Informations d'en-tête de fichier
zip
Ceci explique seulement la différence entre 2 et 3 - pas 4.
Luaan
@Luaan Non, dans les fichiers 2 et 3, les métadonnées de tous les 10 000 fichiers sont incluses dans le ou les fichiers zip. Par conséquent, la taille totale du fichier est presque identique. Dans 4, il n'y a que des métadonnées pour un fichier et le fichier zip est beaucoup plus petit.
Mike Scott
7

Une option manquée par l'OP consiste à compresser tous les fichiers avec la compression désactivée, puis à compresser le zip résultant avec la compression réglée au maximum. Cela imite grossièrement le comportement des archives compressées * nix .tar.Z, .tar.gz, .tar.bz, etc., en permettant à la compression d’exploiter les redondances entre les limites de fichiers (ce que l’algorithme ZIP ne peut pas exécuter lorsqu’il est exécuté dans un seul fichier. passer). Cela permet d'extraire les fichiers XML individuels ultérieurement, mais maximise la compression. L'inconvénient est que le processus d'extraction nécessite une étape supplémentaire, en utilisant temporairement beaucoup plus d'espace disque qu'il n'en faudrait pour un fichier .zip normal.

Avec l'omniprésence d'outils gratuits comme 7-Zip pour étendre la famille tar à Windows, il n'y a vraiment aucune raison de ne pas utiliser .tar.gz ou .tar.bz, etc., car Linux, OS X et les BSD ont tous outils natifs pour les manipuler.

Monty Harder
la source
gzip et bzip2 risquent d’être encore pire, car ils sont conçus pour la compression de flux, ils devront donc commencer à émettre des données compressées avant que toutes les données à compresser ne soient connues.
rackandboneman
@rackandboneman: C'est le compromis que vous devez faire lors de la compression de fichiers dont la taille est supérieure à la quantité de mémoire que vous souhaitez utiliser au moment de la compression. (Et aussi, la quantité de temps de calcul nécessaire pour trouver quelque chose d'optimalement global serait énorme.) Un dictionnaire de compression énorme peut également augmenter la mémoire requise pour la décompression . C'est une option pour LZMA ( xz/ 7-zip). Quoi qu'il en soit, les dictionnaires adaptatifs peuvent récupérer des modèles une fois qu'ils sont visibles. Ce n'est pas comme s'il construisait simplement un système de codage statique basé sur le premier 32k. C'est pourquoi gzip ne craint pas.
Peter Cordes
J'aime vraiment ce "truc" si vous devez rester avec le format zip. Je ne suis pas d'accord avec votre "aucune raison de ne pas utiliser 7-zip" - si j'envoie un fichier à un ami non technique, je veux être sûr qu'il sera capable de l'ouvrir facilement. Si j'envoie à un client professionnel, encore plus.
Wowfunhappy
5

Le format de compression zip stocke et compresse chaque fichier séparément. Il ne tire pas parti de la répétition entre fichiers, mais uniquement au sein d’un fichier.

La concaténation du fichier permet à zip de tirer parti des répétitions de tous les fichiers, ce qui entraîne une compression considérablement plus importante.

Par exemple, supposons que chaque fichier XML ait un certain en-tête. Cet en-tête n'apparaît qu'une seule fois dans chaque fichier mais est répété de manière presque identique dans de nombreux autres fichiers. Dans les méthodes 2 et 3, zip ne pouvait pas compresser pour cela, mais dans la méthode 4, il le pouvait.

BonsaiOak
la source
3
En quoi cela diffère-t-il de l’une des trois principales réponses déjà affichées 5 heures plus tôt?
Xen2050
1
@ Xen2050 Pas beaucoup de différence, je pensais pouvoir l'expliquer plus clairement.
BonsaiOak
1
@BonsaiOak - ajoutez ensuite un commentaire à la réponse correcte ou modifiez-le si vous avez assez de représentants. Si ce n'est pas le cas, mais que votre commentaire ajoute de la clarté, quelqu'un d'autre pourrait le prendre et éditer le message de toute façon.
AdamV
@ AdamV je vois votre point. Ma réponse n’ajoute pour le moment aucune information utile, même si elle l’a fait quand je l’ai écrite. Il y a déjà des commentaires appropriés dans la première réponse, donc je ne vois pas l'intérêt de les ajouter non plus. Voulez-vous dire que je devrais fermer ma réponse? Quel mal y a-t-il à le laisser ouvert?
BonsaiOak
4

Mike Scott a mentionné, à côté des métadonnées, que l’algorithme de compression est surchargé.

Lorsque vous compressez un groupe de petits fichiers individuels, vous devez être très chanceux pour pouvoir les compresser en remplissant un bloc de compression. Lors de la compression d'un seul bloc monolithique, le système peut simplement continuer à transmettre des données à son algorithme, en ignorant les "limites" (faute d'un meilleur mot) des fichiers individuels.

ASCII est également connu pour avoir un facteur de compression élevé. plus xml est souvent très répétitif, faisant des métadonnées une grande quantité de données qui ne peuvent pas être compressées aussi facilement que le contenu xml.

Enfin, si la mémoire est bonne, zip utilise quelque chose comme le codage par dictionnaire, ce qui est particulièrement efficace sur les fichiers ASCII et plus encore sur XML en raison de leur répétitivité.

La compression de données expliquée: http://mattmahoney.net/dc/dce.html

GapWim
la source
3

Considérons ce XML:

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

Un XML a une structure très répétitive, Zip profite de ces répétitions pour créer un dictionnaire dont le modèle contient plus d’occurrences, puis utilise moins de bits pour stocker des modèles plus répétés et plus de bits pour stocker des modèles moins répétés .

Lorsque vous concaténez ces fichiers, le fichier source (la source pour zip) est volumineux, mais contient beaucoup plus de motifs répétés, car la distribution des structures ennuyeuses d'un XML est amortie dans le gros fichier entier, ce qui vous permet d'essayer ZIP pour stocker ces motifs. en utilisant moins de bits.

Maintenant, si vous combinez différents fichiers XML dans un seul fichier, même lorsque ces fichiers portent des noms de balises complètement différents, l'algorithme de compression trouvera la meilleure répartition des modèles entre tous les fichiers et non fichier par fichier.

En fin de compte, l'algorithme de compression a trouvé la meilleure distribution de motifs répétés.

rnrneverdies
la source
-1

En plus de la réponse 7-Zip, il existe une autre approche qui n'est pas aussi bonne mais qui mériterait d'être testée si pour une raison quelconque vous ne voulez pas utiliser 7-Zip:

Compressez le fichier zip. Normalement, un fichier zip est incompressible, mais quand il contient beaucoup de fichiers identiques, le compresseur peut trouver cette redondance et la compresser. Notez que j'ai également constaté un léger gain lorsque je traite un grand nombre de fichiers sans redondance. Si vous vous souciez vraiment de la taille, essayez si vous avez énormément de fichiers dans votre zip.

Loren Pechtel
la source
Cela ne fonctionne que si vous effectuez le premier zip avec la compression désactivée, comme indiqué ci-dessus.
Monty Harder
@MontyHarder Je l'ai vu fonctionner avec la compression activée.
Loren Pechtel