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}]}