ホーム › エンコーディング・圧縮 › E-02
E-02: ZIP/GZIP 圧縮・解凍
java.util.zip の ZipOutputStream・GZIPOutputStream で複数ファイルの ZIP 圧縮と単一ファイルの GZIP 圧縮を解説します。 圧縮レベルのトレードオフと、よくある落とし穴も紹介します。
いつ使うか
- 複数のファイルをまとめて1つのアーカイブに圧縮して配布・転送するとき(ZIP)
- ログファイルやテキストデータをサーバー間で転送する際にサイズを削減するとき(GZIP)
- Web サーバーのレスポンスを GZIP 圧縮してネットワーク転送量を削減するとき
- バックアップファイルを圧縮して保存容量を節約するとき
ZIP と GZIP の比較
| 形式 | ファイル数 | 用途 | クラス |
|---|---|---|---|
| ZIP | 複数可 | ファイル配布・アーカイブ | ZipOutputStream |
| GZIP | 1つのみ | 転送・ログ圧縮 | GZIPOutputStream |
サンプルコード
ZipOutputStream を閉じると自動的に ZIP の終端マーカーが書き込まれます。try-with-resources を使えばクローズ忘れを防げます。
よくあるミス・注意点
⚠️ closeEntry() を忘れると ZIP が壊れる
ZipOutputStream では各エントリのデータを書き込んだ後に必ず closeEntry() を呼んでください。忘れると次のエントリの開始位置が正しく書き込まれず、展開時にエラーになります。
⚠️ ZIP 内にディレクトリ構造を作るにはパスを含めればよい
new ZipEntry("dir/file.txt") のようにスラッシュを含むパスを指定するだけで、ZIP 内にディレクトリ構造を作れます。 ディレクトリ自体は new ZipEntry("dir/") と末尾スラッシュで作成します。
⚠️ GZIP は1ファイルしか圧縮できない
GZIP フォーマットは単一のデータストリームを圧縮するものです。複数ファイルをまとめて GZIP 圧縮したい場合は、 まず tar でまとめて(tar.gz)か ZIP を使ってください。
⚠️ 圧縮レベルは速度と圧縮率のトレードオフ
Deflater.BEST_SPEED(level=1)は圧縮率より速度を優先し、Deflater.BEST_COMPRESSION(level=9)は最大圧縮率を優先します。 リアルタイム圧縮には BEST_SPEED、バックアップには BEST_COMPRESSION が向いています。 デフォルトは level=6 でバランス型です。
テストする観点
- ZIP 圧縮 → 解凍で元のファイル名と内容が一致すること(往復変換)
- GZIP 圧縮 → 解凍で元の文字列と一致すること(往復変換)
- 空のコンテンツ(空文字列)をエントリとして追加しても正常に圧縮・解凍できること(境界値)
- 日本語ファイル名のエントリが正しく圧縮・解凍できること
- バイナリデータ(バイト配列)が正しく圧縮・解凍できること
- 圧縮後のサイズが元のサイズより小さくなること(繰り返しデータで確認)