ZIPファイルを読む(ZIPファイルを解答したい).

今日,夏休みバイナリ入門 2012に参加してきました.
主催者のid:7shiさんが作って下さった,超非常にわかりやすいZIPファイルフォーマットの解説資料を参考にしつつ,ポリポリとプログラムを書きました.ただ,僕の環境で作ったZIPファイルはextra_fieldが入っているようで,ZIP_HEADERとZIP_CENTRAL_HEADERのファイル名の後に,extra_field_lengthバイト分余計なデータがありました.Macかinfo-ZIP特有かもしれません.

まぁ,つってもZIPファイルのフォーマット通り,Pythonの辞書に突っ込んでいるだけです...

実用上問題ならないプログラムにするには,まずファイル末尾のヘッダを読んで,ファイルの一覧を取得してから,ファイル先頭の圧縮されたデータをシークさせながら少しずつ解凍して書き込んでいく必要があります.ですが,今回はファイルのフォーマットを知りたかったので,そういったことは無視し,先頭からバリバリ読んでいます.しかも,解凍の部分は書いていません.今度Pythonで書く予定です.

あと,学校の宿題で,ハフマン符号のプログラムを書いてこい(C言語縛り)という謎課題が出ているので,もうC言語でちょっとまともなZIP解凍プログラムも書こうと思います.

unzip.py

出力結果例(helloと書かれた1.txtとworldと書かれた2.txtを無圧縮したZIPファイル)

{'central_headers': [{'compressed_size': 6,
                      'compression': 0,
                      'crc32': 909783072,
                      'disk_number_start': 0,
                      'dos_date': 16667,
                      'dos_time': 1349,
                      'external_file_attributes': 2175008768,
                      'extra_field': 'UT\x05\x00\x03\xd2C:Pux\x0b\x00\x01\x04\xf5\x01\x00\x00\x04\x14\x00\x00\x00',
                      'extra_field_length': 24,
                      'file_comment_length': 0,
                      'file_name_length': 5,
                      'filename': '1.txt',
                      'flags': 0,
                      'internal_file_attributes': 0,
                      'position': 0,
                      'uncompressed_size': 6,
                      'version': 10,
                      'version_made': 798},
                     {'compressed_size': 6,
                      'compression': 0,
                      'crc32': 3711459752,
                      'disk_number_start': 0,
                      'dos_date': 16667,
                      'dos_time': 1351,
                      'external_file_attributes': 2175008768,
                      'extra_field': 'UT\x05\x00\x03\xd5C:Pux\x0b\x00\x01\x04\xf5\x01\x00\x00\x04\x14\x00\x00\x00',
                      'extra_field_length': 24,
                      'file_comment_length': 0,
                      'file_name_length': 5,
                      'filename': '2.txt',
                      'flags': 0,
                      'internal_file_attributes': 0,
                      'position': 69,
                      'uncompressed_size': 6,
                      'version': 10,
                      'version_made': 798}],
 'end_header': {'central_dir_offset': 138,
                'central_dir_size': 150,
                'disk_number_start': 0,
                'file_coment_length': 0,
                'number_of_disk_entries': 2,
                'number_of_disks': 0,
                'number_of_entries': 2},
 'headers': [{'compressed_size': 6,
              'compression': 0,
              'crc32': 909783072,
              'data': 'hello\n',
              'dos_date': 16667,
              'dos_time': 1349,
              'extra_field': 'UT\t\x00\x03\xd2C:P\xe6C:Pux\x0b\x00\x01\x04\xf5\x01\x00\x00\x04\x14\x00\x00\x00',
              'extra_field_length': 28,
              'file_name_length': 5,
              'filename': '1.txt',
              'flags': 0,
              'uncompressed_size': 6,
              'version': 10},
             {'compressed_size': 6,
              'compression': 0,
              'crc32': 3711459752,
              'data': 'world\n',
              'dos_date': 16667,
              'dos_time': 1351,
              'extra_field': 'UT\t\x00\x03\xd5C:P\xe6C:Pux\x0b\x00\x01\x04\xf5\x01\x00\x00\x04\x14\x00\x00\x00',
              'extra_field_length': 28,
              'file_name_length': 5,
              'filename': '2.txt',
              'flags': 0,
              'uncompressed_size': 6,
              'version': 10}]}