前回からのつづき

前回、Zip ファイルの内部構造について、説明を行ってきました。Zip ファイルの構造が、いかにシーケシャルに頭から書き出すことができるように工夫された形式であるかや、後方互換性を念頭においた設計になっているかについてみてきました。

今回は、展開ソフトやライブラリの Zip ファイルの読み解き方から順番にみていきたいと思います。


展開ソフトはどう読むか?

ここでは、展開ソフトやライブラリが Zip ファイルをどのように読み進めるかについて、通常の zip ファイルをもとに説明します。

展開ソフトは、Zip ファイルを後ろから読みます。

① ファイルの最後へ移動

Zip ・・・・・・・・・・・・・・・・・・EOF

② EOCDを探す

End of Central Directory

③ EOCDを見る

Central Directory は 1234567 バイト目から

④ Central Directoryを読む

sample/test.txt sample/image/photo.jpg

⑤ 必要なファイルだけ取り出す

sample/test.txt

なぜこの設計になっているか?

これは、Zip ファイルが開発された 1989 年頃の パソコン 事情が大きく影響しています。

当時は

  • メモリが数 MB しかない。
  • HDD も非常に小さい。
  • CD-ROM など追記型メディアも使われる。

という時代でした。

そのため、最後に目次だけ追加すれば Zip ファイルを完成できるという設計は、とても都合が良かったのです。

ファイルを書き込みながら圧縮し、最後に「目次」をまとめて書くだけで済むため、途中で全体を作り直す必要がないからです。


Zip ファイルにはフォルダがどのように保存されるのか?

ここまで、読んで、不思議に思われた方もいらっしゃると思います。

Zip ファイルの構造に明確にフォルダを示すものが存在しないからです。

Zip ファイルを実際に作成したことのある方は、お気づきだと思いますが、多くの Zip 圧縮・展開ソフトでは、フォルダごとの圧縮や展開も可能となっています。

では、どのようにして、それを実現しているのでしょうか?

実は、Zip ファイルではフォルダ階層を、主にファイル名に含まれるパスによって表現します。

例えば、

sample/
    image/
        photo.jpg

というファイルを Zip ファイルに格納したとします。

その際、そのファイルの Central Directory や Local File Header のファイル名には、

sample/image/photo.jpg

というパスの形式で保存されます。

では、フォルダは、どうなるのでしょうか? Zip ファイルには、格納できないのでしょうか?

問題ありません。0バイトのフォルダエントリとして格納できます。

例えば、

Local File Header
    ファイル名: "sample/"
    サイズ: 0
    圧縮サイズ: 0
    圧縮データ: なし

Central Directory Entry
    ファイル名: "sample/"
    サイズ: 0
    圧縮サイズ: 0
    Local File Header の位置: ...
    
End of Central Directory

しかし、Zip ファイルの仕様では、必ずしもフォルダだけのエントリーを作成する必要がありません。

例えば、

sample/
    test.txt

を Zip ファイルにするとき、

sample/
sample/test.txt

の2エントリーを作ることもできますが、

sample/test.txt

だけでも構いません。

この場合、

Central Directory
    sample/test.txt

だけが存在しますが、展開ソフトが sample/ を必要に応じて作るため、問題なくフォルダが再現されます。

一方、

sample/
    ← 中身が何もない

という空フォルダーを表現したい場合は、展開時のフォルダー復元のため

sample/

という先述の圧縮データなしのエントリーを Zip ファイル内に持たせる必要があります。


Local File HeaderとCentral Directoryの両方にファイル名などの情報があるのはなぜか?

Local File Header と Central Directory には、ファイル名やサイズなど、一部重複する情報が格納されています。これは無駄に見えるかもしれません。

Local File Header は各ファイルのデータを処理するために、そのデータの直前に置かれます。

一方、Central Directory は Zip ファイル全体の目次として、各ファイルの情報をまとめて管理しています。

👉 このように、それぞれの役割が異なるため、同じような情報が両方に存在しています。


次回予告

今回説明してきた、Zip ファイル形式は、広くその仕様が公開されている関係から、その形式でファイルを圧縮・展開するツールは、数多のものが存在します。

Web クライアントで使用できるライブラリにも、同様に数多くのものが存在します。代表的なものとしては、JSZip や fflate などがあります。

次回以降では、比較的早くから存在し、定番とも呼ばれる JSZip ライブラリについて、その使用方法を中心に説明していきたいと思います。