[前へ] [目次]


圧縮ファイルの形式

この章では、ebzip が扱っている圧縮ファイル形式の詳細について説 明します。

圧縮ファイル形式の概要

圧縮ファイル形式は次のような特徴を持っています。

圧縮されたファイルは、ヘッダ部、インデックス部、およびデータ部から構成 され、この順でファイルに配置されます。

+--------+-------------+-----------------------------+
| ヘッダ |インデックス |          データ             |
+--------+-------------+-----------------------------+
                                                     EOF

データ部

元のファイルは、次の行程で圧縮されます。

まず、ebzip は元のファイルを分割します。 個々の スライス (slice) は、末尾のものを除けば、 同じ大きさになっています。

+---------------+---------------+--   --+----------+
|  スライス 1   |  スライス 2   |  ...  |スライス N|
+---------------+---------------+--   --+----------+
                                                  EOF

スライス・サイズは、圧縮レベルから決まります (圧縮レベルについては 「圧縮レベル」を 参照のこと)。

圧縮レベル スライスの大きさ
0 2048 バイト
1 4096 バイト
2 8192 バイト
3 16384 バイト
4 32768 バイト
5 65536 バイト

次に、末尾のスライスがスライス・サイズよりも短かった場合、 ebzip はスライス・サイズと同じになるまで伸ばし、伸ばした 部分に 0x00 を埋めます。

                                                 伸した部分
+---------------+---------------+--   --+---------+-----+
|  スライス 1   |  スライス 2   |  ...  |  スライス N   |
+---------------+---------------+--   --+---------+-----+
                                                        EOF

最後に、ebzip は個々のスライスを、RFC 1951 に記されている DEFLATE 圧縮データ形式で圧縮します。 おのおののスライスは、他のスライスとは独立して圧縮されます。 圧縮されたスライスのビット数が 8 の倍数でなければ、1 〜 7 ビットを圧 縮されたスライスの末尾に足し、8 の倍数になるようにします。 これにより、圧縮されたそれぞれのスライスはバイトの境界から開始されます。 足されたビットの内容は未定義ですが、このビットは決して使用されません。

+------------+----------+--   --+--------------+
| 圧縮された |圧縮された|  ...  |  圧縮された  |
| スライス 1 |スライス 2|  ...  |  スライス N  |
+------------+----------+--   --+--------------+

これが圧縮ファイル形式における データ部 になり、圧縮された スライスから構成されます。

末尾のスライスの伸ばした部分は、末尾のスライスの一部として圧縮され ます。 ebunzip が末尾のスライスを復元するときは、スライスを伸長して から伸ばした部分を取り除くという作業を行います。

圧縮したスライスの大きさが、スライス・サイズよりも大きいか等しいときは、 ebzip はそのスライスの圧縮データを廃棄します。 この場合、ebzip は元のデータをそのスライスの圧縮データとして 代わりに記録します。

元のファイルが空だったときは、圧縮ファイルのデータ部はありません。

インデックス部

圧縮時に、ebzip は圧縮した個々のスライスの インデックス (index) を記録します。 個々のインデックスは、圧縮ファイルの先頭から圧縮されたスライスの先頭 までの距離を表します。 距離の単位はバイトです。

+---------+---------+--           --+---------+---------+
|インデッ |インデッ |  ...........  |インデッ |インデッ |
|クス 1   |クス 2   |  ...........  |クス N   |クス END |
+---------+---------+--           --+---------+---------+
     |         |                        |         |
 +---+         +----+                   +------+  +-----------+
 V                  V                          V              V
+------------------+------------------+--   --+--------------+
|    圧縮された    |    圧縮された    |  ...  |  圧縮された  |
|    スライス 1    |    スライス 2    |  ...  |  スライス N  |
+------------------+------------------+--   --+--------------+

個々のインデックスは 2 〜 5 バイトの大きさを持ちます。 インデックスの大きさは、元のファイルの大きさで決まります。

元のファイルの大きさ インデックスの大きさ
0 〜 65535 バイト 2 バイト
65535 〜 16777215 バイト 3 バイト
16777216 〜 4294967295 バイト 4 バイト
4294967296 〜 1099511627775 バイト 5 バイト

インデックス内での、複数バイトからなる数値はすべて、値の大きい方の部分 を表すバイト (most significant byte) が先に来た形で記録されます。 たとえば、0x1234 は次のように記録されます。 最初のバイトは 0x12 となり、次のバイトは 0x34 になります。

+---------+---------+
|0001 0010|0011 0100|
+---------+---------+
  (0x12)    (0x34)

インデックス部は、圧縮されたスライス 1 のインデックスで始まり、その後ろ に圧縮されたスライス 2 のインデックスが続きます。 圧縮されたスライス N のインデックスの後ろには、「終端」へのインデックス が置かれます。 このインデックスは、圧縮されたスライス N の末尾の次のバイトへの インデックスになります。 また、圧縮されたファイルのサイズを示すことにもなります。

+---------+---------+--           --+---------+---------+
|インデッ |インデッ |  ...........  |インデッ |インデッ |
|クス 1   |クス 2   |  ...........  |クス N   |クス END |
+---------+---------+--           --+---------+---------+

圧縮されたスライスの大きさがスライスサイズに等しいときは、そのスライス のデータは実際には圧縮されていないことを示します。

元のファイルが空だったときは、インデックス部はインデックスを一つだけ 持ちます。 このインデックスは圧縮されたファイルの大きさを表します。

ヘッダ部

ヘッダ部は 22 バイトからなります。 次のフィールドから構成されます。

+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| マジック ID  |*1| *2  |ファイルの大きさ | Adler-32  | 修正時刻  |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 0  1  2  3  4  5  6  7  8  9  10 11 12 13 14 15 16 17 18 19 20 21

*1: zip モードと圧縮レベル
*2: 予約領域
マジック ID (5 バイト)
0x45, 0x42, 0x5a, 0x69, 0x70 (ASCII 文字列で表すと EBZip) という固定した値を持ちます。
zip モード (MSB 側の 4 ビット)
圧縮モードを表します。 元の (非圧縮時の) ファイルの大きさが 4294967295 バイト (= 4Gバイト) 以内のときは 1 (2 進数で 0001)、それより大きいときは 2 (2 進数で 0002) をセットします。

ファイルの大きさで値が変わるのは、歴史的な事情によります。 以前の EB Library は圧縮モード 1 しか既定しておらず、また 4GB バイト を超えるファイルを扱えませんでした。 4G バイトを超えるファイルを扱えるように EB Library を改良した際に、 「4G バイトを超えたら、圧縮モードは 2 にセットする」というルールを 新たに設けました。 これにより、以前の EB Library で 4GB バイトを超えたファイルを扱おう とすると、非対応の圧縮モードとみなされ、エラーが発生するようになって います。

圧縮レベル (LSB 側の 4 ビット)
圧縮レベルを表します。
予約領域 (2 バイト)
予約されていますが、使われていません。 0x0000 で埋められます。
ファイルの大きさ (6 バイト)
元の (非圧縮時の) ファイルの大きさを記録しています。
Adler-32 (4 バイト)
RFC 1950 に記されている Adler-32 というアルゴリズムを用いて計算した、 非圧縮データのチェックサムの値です。
修正時刻 (4 バイト)
元のファイルの最終修正時刻です。 グリニッジ標準時の 1970 年 1 月 1 日 0 時 0 分 0 秒からの経過秒数で 表します。

zip モード圧縮レベル は、両方ともヘッダの 5 バイト目に入ります。 zip モード は、値の最も大きい部分を表すビット (most significant bit) を含み、圧縮レベル は最も小さい部分を 表すビット (least significant bit) を含んでいます。 zip モード が 1 で、圧縮レベル が 2 なら、 ヘッダの 5 バイト目は 0x12 になります。

 MSB                         LSB
+---+---+---+---+---+---+---+---+
| 0   0   0   1   0   0   1   0 | = 0x12
+---+---+---+---+---+---+---+---+
  (zip モード)  |  (圧縮レベル)

ヘッダ内での、複数バイトからなる数値はすべて、値の大きい方の部分 を表すバイト (most significant byte) が先に来た形で記録されます。


[前へ] [目次]