コンテンツにスキップ

ZIPの圧縮率はなぜファイルによって大きく違うのか

カテゴリ:ファイル形式

「ZIPで圧縮したのにほとんど小さくならなかった」「テキストファイルは圧縮後にサイズが激減した」という経験はありませんか? ZIPの圧縮率はファイルの種類によって大きく異なります。この記事では、その理由と各ファイル形式の特性を解説します。

ファイル種別と圧縮後サイズ(元 100% 比) 0% 100% TXT / CSV ~15% JSON / XML ~20% HTML / CSS / JS ~25% DOCX / XLSX ~90% PDF ~95% JPEG / PNG / MP3 ~99% MP4 / ZIP ~100%
図: ZIP 圧縮率のファイル種別比較(小さいほど効果大)

ZIPで使われる圧縮アルゴリズム:Deflate

ZIPフォーマット(.zip)は主に <strong>Deflate</strong> アルゴリズムを使用します。Deflateは以下の2つの技術を組み合わせたものです。

  • <strong>LZ77(Lempel-Ziv 1977)</strong>:データ中の繰り返しパターンを「以前に出現した位置への参照」で置き換える
  • <strong>ハフマン符号化</strong>:出現頻度の高い文字を短いビット列で表現する

つまり、<strong>繰り返しパターンが多いデータほど圧縮率が高く</strong>、逆にランダムなデータや既に圧縮済みのデータはほとんど圧縮できません。

ファイル形式別の圧縮率

ファイル形式圧縮率(目安)理由
テキスト(.txt)60〜80%削減繰り返し文字・単語が多い
CSV70〜85%削減区切り文字・同パターンが繰り返す
HTML / XML / JSON65〜85%削減タグ・キー名の繰り返しが多い
ログファイル70〜90%削減タイムスタンプ形式の繰り返しが多い
BMP(無圧縮画像)50〜80%削減同色ピクセルの連続が多い
PDF5〜20%削減内部でzlib圧縮済みのケースが多い
PNG0〜5%削減既にDeflateで圧縮済み
JPEG0〜5%削減既にDCT+ハフマンで圧縮済み
MP3 / AAC0〜3%削減既に不可逆圧縮済み
MP4 / H.2640〜3%削減既に高圧縮済み
ZIP / GZ / 7z0〜2%削減(場合によりサイズ増)圧縮済みデータに再圧縮はほぼ無効

圧縮済みファイルがさらに大きくなる場合

JPEGやMP4などの既に圧縮されたファイルをZIPで圧縮すると、ZIPのヘッダー(ファイルメタデータ)分だけ <strong>わずかにサイズが増える</strong> ことがあります。ZIPフォーマットは各ファイルに対してローカルファイルヘッダー(30バイト以上)と、ZIP全体のセントラルディレクトリを持つためです。

JPEGファイル (1.00 MB)
 └── ZIP圧縮後: 1.00 MB + ヘッダー(約50B)= わずかに増加

「Store」モードとの使い分け

ZIPには圧縮せずにファイルを格納する <strong>Store</strong> モードがあります。既に圧縮済みのファイル(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ファイルは、ファイルサイズを正確にコントロールするために、<strong>ランダムデータ(擬似ランダムバイト列)</strong> を格納しています。ランダムデータはエントロピーが最大なので 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の圧縮率は <strong>データの繰り返しパターン</strong> の多さで決まる
  • テキスト・CSV・XMLは <strong>60〜85%削減</strong> できる
  • JPEG・MP4・既圧縮ファイルは <strong>ほぼ圧縮できない</strong>(むしろわずかに増加)
  • 既圧縮ファイルをまとめる場合は <strong>Storeモード(-0)</strong> でCPU節約
  • DevLabのテスト用ZIPはランダムデータを使用しているため、解凍前後でほぼ同サイズ

→ <a href="/ja/files/zip/">テスト用ZIPファイルのダウンロードはこちら</a>

この記事で使えるテストファイル

  • → <a href="/ja/files/zip/" class="text-primary-600 dark:text-primary-400 hover:underline">ZIPテストファイル一覧</a>
  • → <a href="/ja/files/csv/" class="text-primary-600 dark:text-primary-400 hover:underline">CSVテストファイル一覧</a>

関連記事

  • → <a href="/ja/blog/file-format-quick-reference/" class="text-primary-600 dark:text-primary-400 hover:underline">開発者のためのファイル形式クイックリファレンス</a>
  • → <a href="/ja/blog/file-validation-checklist/" class="text-primary-600 dark:text-primary-400 hover:underline">Webフォームのファイルバリデーション実装チェックリスト</a>

🛠️ この記事に関連するツール