ZIPの圧縮率はなぜファイルによって大きく違うのか
「ZIPで圧縮したのにほとんど小さくならなかった」「テキストファイルは圧縮後にサイズが激減した」という経験はありませんか? ZIPの圧縮率はファイルの種類によって大きく異なります。この記事では、その理由と各ファイル形式の特性を解説します。
ZIPで使われる圧縮アルゴリズム:Deflate
ZIPフォーマット(.zip)は主に Deflate アルゴリズムを使用します。Deflateは以下の2つの技術を組み合わせたものです。
- LZ77(Lempel-Ziv 1977):データ中の繰り返しパターンを「以前に出現した位置への参照」で置き換える
- ハフマン符号化:出現頻度の高い文字を短いビット列で表現する
つまり、繰り返しパターンが多いデータほど圧縮率が高く、逆にランダムなデータや既に圧縮済みのデータはほとんど圧縮できません。
ファイル形式別の圧縮率
| ファイル形式 | 圧縮率(目安) | 理由 |
|---|---|---|
| テキスト(.txt) | 60〜80%削減 | 繰り返し文字・単語が多い |
| CSV | 70〜85%削減 | 区切り文字・同パターンが繰り返す |
| HTML / XML / JSON | 65〜85%削減 | タグ・キー名の繰り返しが多い |
| ログファイル | 70〜90%削減 | タイムスタンプ形式の繰り返しが多い |
| BMP(無圧縮画像) | 50〜80%削減 | 同色ピクセルの連続が多い |
| 5〜20%削減 | 内部でzlib圧縮済みのケースが多い | |
| PNG | 0〜5%削減 | 既にDeflateで圧縮済み |
| JPEG | 0〜5%削減 | 既にDCT+ハフマンで圧縮済み |
| MP3 / AAC | 0〜3%削減 | 既に不可逆圧縮済み |
| MP4 / H.264 | 0〜3%削減 | 既に高圧縮済み |
| ZIP / GZ / 7z | 0〜2%削減(場合によりサイズ増) | 圧縮済みデータに再圧縮はほぼ無効 |
圧縮済みファイルがさらに大きくなる場合
JPEGやMP4などの既に圧縮されたファイルをZIPで圧縮すると、ZIPのヘッダー(ファイルメタデータ)分だけ わずかにサイズが増える ことがあります。ZIPフォーマットは各ファイルに対してローカルファイルヘッダー(30バイト以上)と、ZIP全体のセントラルディレクトリを持つためです。
JPEGファイル (1.00 MB)
└── ZIP圧縮後: 1.00 MB + ヘッダー(約50B)= わずかに増加
「Store」モードとの使い分け
ZIPには圧縮せずにファイルを格納する Store モードがあります。既に圧縮済みのファイル(JPEG、MP4など)を複数まとめる場合は、Storeモードを使うと圧縮処理のCPU負荷をなくしながら同等のサイズで格納できます。
# zip コマンドで圧縮レベルを指定
zip -0 archive.zip image.jpg video.mp4 # Store(圧縮なし)
zip -9 archive.zip data.csv report.txt # 最大圧縮
# Python で圧縮レベルを指定
import zipfile
with zipfile.ZipFile('archive.zip', 'w', zipfile.ZIP_DEFLATED, compresslevel=9) as zf:
zf.write('data.csv')
テスト用ZIPファイルの特性
DevLab のテスト用ZIPファイルは、ファイルサイズを正確にコントロールするために、ランダムデータ(擬似ランダムバイト列) を格納しています。ランダムデータはエントロピーが最大なので Deflate でほぼ圧縮されません。そのため、「10MBのZIPファイル」= 「解凍後も10MB前後」となります。
もし「解凍後に特定のサイズになるZIPが必要」という場合は、以下のような方法でテスト用ファイルを作成できます。
# 解凍後ちょうど 100MB になるZIPを作成(ゼロバイト埋め、高圧縮)
dd if=/dev/zero bs=1M count=100 | zip -9 zero-100mb.zip -
# 解凍後ちょうど 100MB になるZIPを作成(ランダムデータ、ほぼ無圧縮)
dd if=/dev/urandom bs=1M count=100 | zip -0 random-100mb.zip -
まとめ
- ZIPの圧縮率は データの繰り返しパターン の多さで決まる
- テキスト・CSV・XMLは 60〜85%削減 できる
- JPEG・MP4・既圧縮ファイルは ほぼ圧縮できない(むしろわずかに増加)
- 既圧縮ファイルをまとめる場合は Storeモード(-0) でCPU節約
- DevLabのテスト用ZIPはランダムデータを使用しているため、解凍前後でほぼ同サイズ