Zipが単一のファイルを同じコンテンツの複数のファイルよりも小さく圧縮できるのはなぜですか?


126

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を作成する

コマンド:

zip all.zip $(ls -1)

結果:

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

方法4:ファイルを1つのファイルに連結して圧縮する

コマンド:

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

結果:

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

質問:

  • 単一のファイルを圧縮するだけで、こんなに劇的に良い結果が得られるのはなぜですか?
  • 方法2よりも方法3を使用すると劇的に良い結果が得られると期待していましたが、そうではありません。どうして?
  • この動作は固有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)

編集:メタデータ

1つの答えは、その違いはzipに保存されているシステムメタデータであることを示唆しています。これが当てはまるとは思いません。テストするために、次のことを行いました。

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

結果のzipは1.4MBです。これは、説明されていないスペースがまだ約10 MBあることを意味します。


34
誤解しない限り、.tar.gzディレクトリ全体を圧縮するのとは対照的に、人々がそうするのはこの現象です。
corsiKa

18
同様の問題はすでに、TLを頼まれた; DRは固体7zipをアーカイブを使用しています。
ドミトリーグリゴリエフ

3
@sixtyfootersdudeいくつかの答えを検証するテストとして、方法3で作成されたzipを圧縮してみてください。私は、これは方法4と同等の何かにファイルサイズを小さくします疑う
トラヴィス

7
代わりに$(ls -1)、単に使用し*ますfor x in *zip all.zip *
ムル

4
ZIPで確実な圧縮を行いたい場合は、次善策があります。まず、すべてのファイルを含む非圧縮 ZIPを作成します。次に、そのZIPを別の圧縮ZIPの中に入れます。
user20574

回答:


129

Zipは、圧縮時に各ファイルの内容を個別に扱います。各ファイルには独自の圧縮ストリームがあります。圧縮アルゴリズム(通常はDEFLATE)内で、繰り返しセクションを識別するためのサポートがあります。ただし、ファイル間の冗長性を見つけるためのZipのサポートはありません。

そのため、コンテンツが複数のファイルにある場合、余分なスペースが非常に多くなります。同じ圧縮ストリームをファイルに複数回配置することになります。


9
また、一部の圧縮ツールでは、ファイルを個別に圧縮するか、単一のエンティティとして圧縮するかを選択できます。(一般的には、アーカイブを1つだけ表示したい場合よりも多くのアーカイブを解凍する必要があることも意味します。)
JAB

28
@JAB:7zやrarのような圧縮ツールは、複数のファイルを大きな圧縮ストリームに頭から尾までパックするために「ソリッド」アーカイブという用語を使用します。64MiBのような中程度のチャンクサイズでは、単一のファイルへのランダムアクセスには、圧縮ブロックの開始から最大64MiBのデータの圧縮解除が必要になる場合があります。7zは、より効果的な(ただし圧縮に時間がかかる)LZMA圧縮スキームを使用できます。これは、zipに対するもう1つの利点です。
ピーターコーデス

あなたはそれthere is no support in Zip to find redundancy between filesがzipファイル仕様にあると言っていますか?
sixtyfootersdude

6
@sixtyfootersdude DEFLATEなどの多くの圧縮アルゴリズムは、ストリームとして動作します。ストリームの一部を解凍するのに十分な情報を回復するには、その時点までストリーム全体を処理する必要があります。ファイル間の冗長性を見つけようとした場合、最後のファイルに到達するためには1000個すべてのファイルを解凍する必要があります。これは通常、実際にtgzが機能する方法です。ただし、zipは個々のファイルを抽出できるように設計されています。tgzはよりオールオアナッシングになるように設計されています
Cort Ammon

1
@sixtyfootersdude-それは正しい。Cortを言い換えると:pkzipの仕様は、クロスファイルの機能をサポートしていません。その場合、1つのファイルを抽出するには、アーカイブ全体(およびすべてのファイル)を抽出する必要があります。
ジェームズスネル

48

ZIP圧縮は、圧縮されるデータ内の反復パターンに基づいており、ファイルが長くなればなるほど圧縮が向上します。これは、パターンをより多く見つけて使用できるためです。

簡略化すると、1つのファイルを圧縮すると、(短い)コードを(長い)パターンにマッピングする辞書が、結果の各zipファイルに必ず含まれます。1つの長いファイルを圧縮すると、辞書は「再利用」され、すべてのコンテンツでさらに効果的になります。

ファイルが(テキストが常にそうであるように)少しでも似ている場合、「辞書」の再利用は非常に効率的になり、結果ははるかに小さい合計zipになります。


3
ZIPはアーカイブと圧縮の両方を行います。これは、それらがすべて同じZIPファイルで終わる場合でも、ZIPは各ファイルを個別に圧縮することを意味しますか?
gerrit

2
ある種のファイルを削除することを想像してください。新しい「辞書」で残りを再圧縮するのにさらに30分かかるとは思わないでしょう。-また、おそらく、異なるファイルには非常に異なる「辞書」が必要であると想定しています。
アガンジュ

2
なぜそうなのかわかりません。Unixツールでは、まずファイルをtarでアーカイブし、次にgzip / bz2 / lzmaで圧縮します。圧縮アルゴリズムは、アーカイブにエンコードされているファイルの数を気にしません。また、圧縮されたアーカイブから単一のファイルを削除することは実際にはどのくらい一般的ですか?私はそれをやったことがないと思う。
ヘリット

4
私は同意しません、そしてそれはおそらく良い方法です。私はZIPをデザインしたり書いたりしませんでした。私はそれが何をするか...と
Aganju

16
@gerrit独自の問題があります。Zipは、アーカイブ内の任意のファイルにすばやくアクセスできるように設計されています。100GiB UHAアーカイブから単一のファイルを解凍すると、この方法を選択した理由がわかります。また、追加用に設計されています-バックアップzipを保持し、必要に応じてファイルを追加(または置換)し続けることができます。これらはすべて、アーカイブを使用する際に非常に役立ちます。トレードオフは、非常によく似たファイル(あまり一般的ではない)を圧縮する場合、アーカイブサイズを削減するために類似性を活用できないことです。
ルアーン

43

Zipでは、各ファイルは個別に圧縮されます。反対は「固体圧縮」です。つまり、ファイルは一緒に圧縮されます。7-zipおよびRarはデフォルトで固定圧縮を使用します。GzipおよびBzip2は複数のファイルを圧縮できないため、Tarが最初に使用され、固体圧縮と同じ効果があります。

ファイルが一緒に圧縮されている場合、xmlファイルは類似した構造とおそらく類似したコンテンツを持っているため、圧縮率は高くなります。

たとえば、ファイルに文字列が含まれて"<content><element name="おり、コンプレッサーが別のファイルでその文字列を既に検出している場合、コンプレッサーが文字列の最初の出現を「固体圧縮」を使用しない場合、前の一致への小さなポインターに置き換えますファイルはより大きなリテラルとして記録されます。


9

Zipはファイルの内容を保存するだけでなく、所有ユーザーID、権限、作成および変更時間などのファイルメタデータも保存します。ファイルが1つの場合、メタデータのセットが1つあります。10,000個のファイルがある場合、10,000個のメタデータセットがあります。


3
良い点ですが、システムメタデータは1.4MBのスペースを占有しています。編集をご覧ください。
sixtyfootersdude

1
私はzipアルゴリズムに精通していませんが、メタデータはファイル情報だけでなく、サイズや辞書など、文字の分布に関する情報でもあります。空でないテキストファイルの辞書はゼロ以外になります。おそらく、空のファイルよりもxmlファイルの方がメタデータが大きいのがわかるでしょう。
ベンリチャーズ

これが私の最初の考えでした。ジップファイルヘッダー情報
WernerCD

これは2と3の違いを説明するだけで、4ではありません。
Luaan

@Luaanいいえ、2と3の両方で、10,000個のファイルすべてのメタデータがzipファイルに含まれているため、合計ファイルサイズはほぼ同じサイズです。4では、1つのファイルのメタデータのみがあり、zipファイルははるかに小さくなっています。
マイクスコット

7

OPが見逃したオプションは、圧縮をオフにしてすべてのファイルを圧縮し、圧縮結果を最大に設定して圧縮します。これにより、* nix .tar.Z、.tar.gz、.tar.bzなどの圧縮アーカイブの動作を大まかにエミュレートします。これにより、圧縮がファイル境界を越えて冗長性を利用できるようになります(ZIPアルゴリズムは単一で実行すると実行できません)パス)。これにより、個々のXMLファイルを後で抽出できますが、圧縮は最大化されます。欠点は、抽出プロセスに追加の手順が必要であり、通常の.zipに必要なディスク容量よりも一時的に多くのディスク容量を使用することです。

tarファミリーをWindowsに拡張する7-Zipなどの無料ツールが広く普及しているため、Linux、OS X、およびBSDがすべて持っているように、.tar.gzや.tar.bzなどを使用しない理由は本当にありません。それらを操作するネイティブツール。


gzipおよびbzip2は、圧縮ストリームを念頭に置いて設計されているため、さらに悪化する可能性があります。したがって、圧縮するデータがすべてわかる前に、圧縮データの出力を開始する必要があります。
rackandboneman

@rackandboneman:これは、圧縮時に使用するメモリの量よりも大きいファイルを圧縮する場合に行う必要があるトレードオフです。(また、グローバルに最適なものを見つけるために必要なCPU時間は膨大になります。)巨大な圧縮辞書は、解凍に必要なメモリを増やすこともできます。これは、LZMAのオプションです(xz/ 7-zip)。とにかく、アダプティブディクショナリは、パターンが表示されるとパターンを取得できます。最初の32kに基づいて静的コーディングシステムを構築するだけではありません。これが、gzipがうまくいかない理由です。
ピーターコーデス

zip形式のままにする必要がある場合、この「トリック」が本当に好きです。「7-zipを使用しない理由はありません」という意見には同意しません。技術に詳しくない友人にファイルを送信する場合は、彼らが簡単にファイルを開くことができるようにしたいと思います。ビジネスクライアントに送信する場合は、さらにそうです。
Wowfunhappy

5

zip圧縮形式は、各ファイルを個別に保存および圧縮します。ファイル内の繰り返しのみを利用するのではなく、ファイル内でのみ利用します。

ファイルを連結すると、zipはすべてのファイルの繰り返しを利用できるため、圧縮率が大幅に向上します。

たとえば、各XMLファイルに特定のヘッダーがあるとします。そのヘッダーは各ファイルで1回だけ発生しますが、他の多くのファイルでもほぼ同じように繰り返されます。方法2および3では、zipはこのために圧縮できませんでしたが、方法4では圧縮できました。


3
これは、5時間前に既に投稿された上位3つの回答の1つとどのように違いますか?
Xen2050

1
@ Xen2050大した違いはありませんが、もっと明確に説明できると思いました。
BonsaiOak

1
@BonsaiOak-正解にコメントを追加するか、十分な担当者がいる場合は編集します。そうでない場合でも、あなたのコメントが明確になると、他の誰かがこれを拾って、とにかく投稿を編集するかもしれません。
AdamV

@AdamVあなたの主張がわかります。私の答えは現時点では有用な情報を追加していませんが、私が書いたときに間違いなく追加しました。最初の回答の下にはすでに適切なコメントがありますので、それらを追加する意味もわかりません。私の答えを閉じるだけだと言っていますか?開いたままにしておくとどのような害がありますか?
盆栽オーク

4

マイク・スコットが言及したメタデータの隣には、圧縮アルゴリズムにもオーバーヘッドがあります。

個々の小さなファイルを大量に圧縮する場合、たった1つの圧縮ブロックを埋めることができるので、それらを圧縮できるようにすることは非常に幸運でなければなりません。単一のモノリシックブロックを圧縮する場合、システムは、個々のファイルの「境界」(より良い単語がないため)を無視して、アルゴリズムにデータをストリーミングし続けることができます。

また、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ファイルを圧縮します。現在、通常zipファイルは圧縮できませんが、同じファイルが多数含まれている場合、コンプレッサーはこの冗長性を見つけて圧縮できます。冗長性のない多数のファイルを扱うとき、私は小さな利益を見たことにも注意してください。サイズが本当に気になる場合は、zipに大量のファイルがある場合は試してみる価値があります。


上記のように、圧縮をオフにして最初のzipを実行する場合にのみ機能します。
モンティハーダー

@MontyHarder圧縮を有効にすると動作するのを見ました。
ローレンペクテル
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.