ByteScope

BZIP2 ファイル形式

bzip2 で圧縮されたデータ。Burrows-Wheeler ブロックソート法を使います。

MIME タイプ
application/x-bzip2
拡張子
.bz2
カテゴリ
アーカイブ・圧縮

マジックナンバー(ファイル署名)

0x00000000425A68BZh'BZh' header

BZIP2 形式について

bzip2 は Burrows-Wheeler 変換を使い、gzip より圧縮率は高いものの速度は落ちます。Unix のソース tarball でよく見かけます。ヘッダは BZh に続いてブロックサイズを表す 1 桁の数字です。その 4 バイトから先、ファイルはバイト単位であることをやめます。ブロック、ハフマンテーブル、符号化されたシンボルが位置合わせなしに 1 ビットずつ詰め込まれるからです。バイト境界から始まるのは最初のブロックだけで、hex エディタで bzip2 ファイルの先頭は見えても途中は見えないのはそのためです。その代償として得られるのが、各ブロックが独立していることです。おかげで破損は封じ込められ、復旧も現実的にできます。

ヘッダーの構造(バイト単位)

オフセット長さフィールド意味
02'BZ' magic42 5A。印字可能な文字が 2 つで、バイナリ形式としては珍しく、hex ダンプに BZh が読めるテキストとして現れるのはそのためです。
21Version byteh(0x68)で、ハフマン符号を表します。0.9.0 以降このツールが出力した唯一のバージョンで、デコーダもこれ以外を受け付けません。つまり見慣れた 3 バイトの接頭辞は、マジック単体ではなくマジックとバージョンの組です。
31Block-size digit1 から 9 の ASCII 数字で、ブロックサイズを 100 kB 単位で表します。9 は 0x39 で 900 kB、これが既定値です。圧縮時、そしてより重要なことに展開時のメモリ使用量を決めるので、書き手が一度選べば、すべての読み手がそれに従わなければなりません。
46First block magic31 41 59 26 53 59、円周率の桁をパック 10 進数で並べたものです。バイト境界に載るのはここ、つまり最初のブロックの先頭だけです。以降のブロックにある同じ値は、前のブロックがたまたま終わったビット位置に置かれます。
104Block CRC-32このブロックの非圧縮データのチェックサムで、これもバイト境界に載るのは最初のブロックだけです。部分的な復旧が意味を持つのはブロックごとのチェックサムのおかげで、どのブロックが壊れたかを正確に言い当てられます。
14variableRandomised flag and BWT origin pointer廃止された 1 ビットのフラグ(今世紀に書かれたものでは常に 0)に続いて、元の順序を復元する Burrows-Wheeler 行列の行を指す 24 ビットのポインタが入ります。ここから先はバイト境界がまったくありません。シンボルマップ、ハフマンテーブル、セレクタ、符号化データが連続したビットストリームになります。
variable6End-of-stream magic17 72 45 38 50 90、円周率の平方根の桁で、これ以上ブロックが続かないことを示します。位置はファイルの終わり近くですが、ビットオフセットは手前のすべてによって決まるので、末尾からの距離は固定ではありません。
variable4Combined CRC-32全ブロックの CRC を順に組み合わせた値で、終端マジックの直後に置かれ、その後ろにファイルがバイト境界で終わるよう 0〜7 ビットのパディングが付きます。bzip2 が持つ唯一のファイル全体の整合性値です。

似た形式との見分け方

紛らわしい形式見分け方
GZIPBZh に数字が続く形と 1F 8B です。スクリプトの中での使われ方は同一で拡張子も絶えず取り違えられますが、共有しているものは他に何もありません。gzip は deflate ストリームの上に載ったバイト境界のヘッダ、bzip2 はブロックごとのチェックサムを持つビットストリームの上に載った 4 バイトのヘッダです。
7-Zipこちらは逆向きの誤検出が待ち構えています。7-Zip 自身のマジックは 37 7A で始まり、7z と読めます。そして 7z アーカイブは内部の圧縮方式として bzip2 を使えるので、.7z ファイルの中に BZh の文字列が現れます。決めるのはオフセット 0 だけで、.7z はそこが 37 7A BC AF 27 1C です。
ZIPZIP の圧縮方式 12 は bzip2 なので、ZIP エントリのデータがローカルファイルヘッダと可変長フィールドの直後に BZh から始まることがあります。ファイルの中から BZh を探して .bz2 だと結論づけるのは、オフセット 0 が 50 4B 03 04 である限り常に誤りです。
XZ大半のソース配布でこれを置き換えた形式です。XZ は FD 37 7A 58 5A 00 で始まり、より高い圧縮率に届きます。bzip2 に残った優位は、ブロックが独立していることです。xz のブロックは既定では独立していません。
pbzip2/lbzip2並列圧縮ツールは、完結した独立の bzip2 ストリームを連結して出力します。したがって BZh がファイルの中にバイト境界の位置で繰り返し現れ、円周率のブロックマジックはストリームごとに 1 回ずつ出てきます。できあがるものは通常の展開器が最後まで読める合法な .bz2 のままです。

よくある壊れ方

  • 途中切れ。切れた位置より手前の完全なブロックはすべてデコードできます。ブロックが互いに依存していないからです。bzip2recover が突いているのがまさにそこで、円周率のブロックマジックごとにビットストリームを切り分け、各ブロックをそれぞれ小さな .bz2 として書き出します。壊れたアーカイブから、1 ブロック分を除く全データが戻ってきます。
  • ブロック内部のビット反転。ブロックはハフマン符号化されているので、破損はたいてい終端に着く前にデコードを脱線させます。チェックサム不一致ではなくデータエラーです。デコードが終端まで到達した場合は、オフセット 10 のブロックごとの CRC が捕まえ、どのブロックが失敗したかを名指しします。
  • テキストモード転送。ビットストリーム内の改行変換は、壊れたバイトより後ろすべてを 8 ビットずらすので、4 バイトのヘッダは無傷でファイルも正しく認識されるのに、デコードはほぼ即座に失敗します。
  • ブロックサイズの数字を手で書き換えた場合。9 を 1 に変えても、どの検出器から見てもまだ bzip2 に見えるファイルが残り、最初のブロックで失敗します。展開器はその 1 バイトからバッファサイズを決めるからです。
  • 連結ストリームが途中で切れた場合。並列圧縮したアーカイブは 1 ファイルの中に複数のストリームが入っているので、末尾を失っても最後のストリームだけが失われ、手前のものはきれいに展開できます。途中までダウンロードした pbzip2 のファイルから中身の大半が取り出せることが多いのは、そのためです。

この形式の現在地

bzip2 の時代はおおよそ 1999 年から 2010 年で、ソース tarball を gzip から一段上げるなら当然の選択でした。インターネット上に保管されたソフトウェアの相当な量が今も .tar.bz2 で、それだけでデコーダは永遠に配られ続けます。新規の用途では両側から挟まれています。xz は同等かそれ以上の展開速度で目に見えて小さくなり、Zstandard は gzip 並みの圧縮率をはるかに速い圧縮で出すので、ディストリビューションは何年も前に離れました。上流の勢いもありません。オリジナルの実装は 10 年ほど事実上メンテナンスされていませんでした。それでも擁護できるのはブロック構造です。ブロックが独立しているので pbzip2 で圧縮を簡単に並列化できますし、よくある Unix の圧縮ツールの中では唯一、壊れたアーカイブを最初の不良バイトで諦めるのではなくブロック単位で救い出せます。

BZIP2 ファイルをこのサイトで開く

どれもブラウザ内で動きます。ファイルが端末から出ることはありません。

関連する形式

BZIP2 と混同しやすい形式です。先頭バイトを見比べてください。

形式先頭バイト拡張子
GZIP1F 8B.gz
XZFD 37 7A 58 5A 00.xz
Zstandard28 B5 2F FD.zst
TAR75 73 74 61 72.tar

よくある質問

ファイルのマジックナンバーとは何ですか?

ファイル先頭の数バイトで、名前が何であろうとその形式を示すものです。PNG は必ず 89 50 4E 47 で始まり、ZIP は 50 4B 03 04 で始まります。OS もブラウザも file コマンドも、拡張子を信用せずこのバイト列を読みます。だからファイル名を変えても中身の正体は変わりません。

マジックナンバーを自分で確認する方法は?

macOS や Linux なら xxd -l 16 ファイル名 で先頭 16 バイトが表示されます。Windows なら PowerShell で Format-Hex -Path ファイル名 -Count 16 です。あるいはこのサイトのファイル形式判別ツールにドロップすれば、ローカルでバイト列を読んで形式を教えてくれます。アップロードはありません。

2 つの形式が同じマジックナンバーを持つのはなぜ?

一方が他方の上に作られているからです。docx、xlsx、pptx、apk、jar、epub はすべて中身が ZIP アーカイブなので ZIP の署名で始まり、区別するには内部のエントリを見る必要があります。Java の class ファイルと macOS のユニバーサルバイナリはどちらも CA FE BA BE で始まり、直後のフィールドで見分けます。

マジックナンバーがまったくないファイルもある?

あります。XML、HTML、JSON、SVG、CSV といったテキストベースの形式には固定のバイト署名がないため、構造から判別します。先頭の <?xml 宣言、<svg 要素、あるいは { に続く引用符付きのキーなどです。これは確定ではなく推測なので、このリファレンスではそうした形式をプローブ判別として示しています。

マジックナンバーが一致すればそのファイルは安全?

いいえ。わかるのは形式であって、中身が無害かどうかではありません。正規の PDF や docx でも悪意のあるペイロードを含んでいることがあります。特に拡張子とバイト列が食い違うときに真の形式を知るのは有用な第一段階ですが、マルウェアスキャンではありません。

BZIP2 かもしれないファイルをお持ちですか?ファイル形式判別ツールで調べる — マジックナンバーをローカルで読み取ります。アップロードは一切ありません。またはすべての形式を見る。