kenju's blog

About Programming, Mathematics, Security and Blockchain

Zip Fileの構造詳細と分割の仕組みについて

tl;dr

  • Zip Fileを分割してユーザーに送信する仕組みを実装した際に、そもそもZip Fileは分割できるのか、なぜ分割できるのかについて理解するために調べた
  • Zip Fileを操作する時の基本的なLinux Commands例をメモ

構造

Zip Fileは、主に以下の3つの要素によって成り立つ:

  • Central Directory
  • Local Header
  • File Entry

f:id:itiskj:20170923085938p:plain

retrieved from https://en.wikipedia.org/wiki/Zip_(file_format)#Structure

Central Directory

  • Zipファイル内で各File Entryが位置するオフセットを持つことで、ファイルリストの表示速度をあげることができる(ファイルリストを参照する際に、線形探索するのではなく、Central Directoryのオフセットから一発で探索できるため)
  • 各File Entryの名前やメタデータも持つ
  • Central Directory内のFile Entryの順番は、アーカイブ内の実際の順番と関係なく、同じである必要はない

Local Header

  • 冗長性確保のため、Central Directoryが持つ情報と同じものを保持する
  • ファイルコメント、ファイルサイズ、ファイル名、続く「Extra」フィールドについての情報などを保持する

Extra Fields

  • 暗号化の手段、圧縮方式などを保存するフィールド

File Entry

  • 実際のファイルのデータ。圧縮されたり暗号化されたりしている。

Zip File分割の背景

もともとフロップーディスクなどの小さい記憶容量媒体に、大容量のZip Fileを保存する時、分散して保存できるような仕組みが必要だった、とのこと。

The .ZIP specification also supports spreading archives across multiple filesystem files. Originally intended for storage of large .ZIP files across multiple floppy disks, this feature is now used for sending .ZIP archives in parts over email, or over other transports or removable media.

Zip File操作のためのLinux Commands

分割・統合を含めて、Zip File操作の基本的なコマンド例の備忘録。

Create

$ zip my.zip file1 file2 file3
  adding: file1 (stored 0%)
  adding: file2 (stored 0%)
  adding: file3 (stored 0%)

Read

vimコマンドでzipファイルの中身を直接見ることができる。 コメントに書いてある通り、それぞれのFile Entryの中身を個別に見ることもできる。

" zip.vim version v27
" Browsing zipfile /path/to/my.zip
" Select a file with cursor and press ENTER

file1
file2
file3

Split

splitコマンドが使える。例えば5Mごとに分割する場合。

$ split -b 5M my.zip

creating file `xaa'

creating file `xab'

creating file `xac'

creating file `xad'

creating file `xae'

Join

catコマンドを使う。

$ cat x* > ~/joinedfile

Check

JoinしたZip Fileに問題がないかチェックする。

        -T
       --test
              Test the integrity of the new zip file. If the check fails, the old zip file is unchanged and (with the  -m
              option) no input files are removed.

実行例:

$ zip -T my.zip
test of my.zip OK

Extract

$ unzip mike.zip -d ~/output
Archive:  my.zip
 extracting: /workdir/output/file1
 extracting: /workdir/output/file2
 extracting: /workdir/output/file3