ZIP・7z圧縮実験室

← トップへ
DATA COMPRESSION IN YOUR BROWSER

同じ並びを、もう一度書かない

ZIPと7zは、ファイルを小さくしてまとめるための「箱」です。箱の中でデータを小さくする方法として、ZIPではDEFLATE、7zではLZMA2がよく使われます。

● 入力はブラウザ内だけで処理
ZIP + DEFLATE近くにある繰り返しを探し、よく出る記号には短い番号を割り当てる方式。展開が速く、多くの環境で開けます。
7z + LZMA2もっと広い範囲から繰り返しを探し、次に来そうな記号も予測して小さくする方式。高い圧縮率を狙えます。

最初に知っておく言葉

名前は難しく見えますが、基本は「繰り返しを見つける」「よく出るものを短く書く」の2段階です。

可逆圧縮小さくした後、1文字・1バイトも変えずに完全に元へ戻せる圧縮。ZIPと7zはこれです。
バイトコンピューターがデータを扱う単位。英字はUTF-8で通常1バイト、日本語は通常1文字3バイトです。
辞書国語辞典ではなく、すでに読んだデータを覚えておく範囲。「前にも同じ並びがあったか」を探します。
リテラル別の場所を参照せず、そのまま記録する1バイト。まだ登場していない文字などに使います。
長さ・距離繰り返しを示すメモ。「6バイト前から3バイトコピー」のように、同じ内容を再記録せず表します。
符号化記号を0と1の並びへ割り当てること。出やすい記号を短く表すほど、全体を小さくできます。
例: ABCABCABC → 最初の ABC はそのまま保存 → 残りは「3バイト前から6バイトコピー」と記録。展開するときは、この指示を逆にたどって元の文字列を完全に復元します。

文章を圧縮してみる

入力をUTF-8のバイトに変え、過去に同じ並びがないか探します。繰り返しが多い文章と、短い文章・ランダムな文章を比べてみてください。

元データの大きさ--
DEFLATEで実際に圧縮--
DEFLATE風の繰り返し--
LZMA2風の繰り返し--

「解析する」を押すと結果を表示します。

ZIP側:DEFLATEの入口

32 KiB以内の過去から、3バイト以上の最長一致を探します。青はそのままのバイト、紫は辞書参照です。各トークンにマウスを重ねると元の文字とサイズを確認できます。

リテラル長さ・距離
未解析

7z側:LZMA2の入口

この教材では最大1 MiBの過去を探索します。実際のLZMA2は、直近距離の再利用や文脈別の確率も利用します。各トークンにマウスを重ねると元の文字とサイズを確認できます。

リテラル長さ・距離
未解析

圧縮ファイルができるまで

1. バイト化文字や画像をバイト列として読む。日本語はUTF-8で通常1文字3バイト。
2. 辞書参照過去と同じ並びを探し、リテラルまたは「長さ・距離」に変換。
3. 符号化DEFLATEはハフマン符号、LZMA2は確率モデルと範囲符号化を使う。
4. 容器へ格納ファイル名、日時、CRCなどと一緒にZIPまたは7zへ収める。
ZIPとDEFLATEは同じもの?

同じではありません。ZIPは複数ファイルと名前などをまとめるアーカイブ形式で、DEFLATEはZIPで広く使われる圧縮方式です。ZIPは保存(無圧縮)など別方式も指定できます。各ファイルを基本的に個別圧縮するため、別ファイル間の繰り返しは通常共有しません。

7zとLZMA2は同じもの?

7zもアーカイブ形式で、LZMA2はよく使われる圧縮方式です。7zは複数ファイルを連続データのように圧縮する「ソリッド圧縮」が可能で、似たファイルが多いと有利です。ただし途中の1ファイルだけを取り出すのに前方からの展開が必要になる場合があります。

DEFLATE(デフレート)は何をしている?

DEFLATEは、LZ77とハフマン符号という2つの考え方を組み合わせた、データを失わない圧縮方式です。

  • LZ77:今いる場所から最大32 KiB(32×1024バイト)前までを見て、同じ並びを探します。見つけた並びは「距離」と「長さ」に置き換えます。名前のLZは考案者LempelとZiv、77は発表年の1977年を表します。
  • ハフマン符号:登場回数が多い記号へ短いbit列、少ない記号へ長いbit列を割り当てます。例えばAが非常に多ければAを 0、少ない記号を 10110 のように表し、平均の長さを縮めます。

つまり、最初に「同じ並びを省略」し、その結果に対して「よく出る記号を短く」します。展開側は保存された符号表を読み、短い記号を戻してから、距離・長さの指示どおり過去のデータをコピーします。

LZMA2(エルゼットエムエー・ツー)は何をしている?

LZMAは Lempel–Ziv–Markov chain Algorithm の略です。DEFLATEと同様に過去の一致を利用しますが、より大きな辞書を選べ、次に現れるデータの確率も細かく予測します。LZMA2はLZMAを扱いやすく拡張し、データを複数の区切りに分けたり、圧縮しにくい部分をそのまま格納したり、並列処理しやすくした方式です。

  • 文脈モデル:直前の文字や、今がリテラルか繰り返しかなど、周辺の状況ごとに「次は何が出やすいか」を学習します。
  • 範囲符号化:記号ごとに固定のbit列を付ける代わりに、予測確率に応じて数値の範囲を狭めていきます。出やすい記号ほど少ない情報量で表せます。
  • 大きな辞書:かなり前に出た同じ並びも参照できます。見つけやすくなる一方、設定した辞書サイズに応じて多くのメモリを使います。

このためLZMA2はDEFLATEより小さくできる場合がありますが、圧縮には一般に多くの計算時間とメモリが必要です。どんなデータでも必ず小さくなるわけではありません。

DEFLATEとLZMA2の主な違い
  • 辞書:DEFLATEの参照距離は最大32 KiB。LZMA2は設定によりはるかに大きな辞書を使えます。
  • 符号化:DEFLATEは記号頻度から作るハフマン符号。LZMA系は周辺の状況から確率を予測するモデルと範囲符号化を組み合わせます。
  • 資源:大きい辞書は遠い繰り返しを見つけやすい反面、圧縮・展開時のメモリ使用量が増えます。
  • 用途:ZIPは広い互換性と取り出しやすさ、7zは高い圧縮率を重視するときに選ばれやすい方式です。

結果を読むときの注意

紫のトークンは、このページが辞書一致を実際に探索した結果です。「参照命令 ○ byte」は長さと距離を一般的な可変長整数で記録した場合の、この教材内での比較値です。実際のDEFLATEは2つのハフマン符号と追加bit、LZMA2は確率に応じた範囲符号を使うため、参照1個の最終バイト数は固定ではありません。LZMA2の最終サイズは算出せず、7zファイルも生成しません。DEFLATE実測値はZIPのヘッダーやファイル名を含まない生の圧縮ストリームなので、実際のZIPファイル容量とは異なります。