55
46

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Python 3 で日本語ファイル名が入った zip ファイルを扱う

Posted at

zip ファイルは最近の仕様では UTF-8 でファイル名を格納できるのですが、多くの場合レガシーな環境依存文字コードでファイル名が格納された形式が使われています。日本語の場合は Windows に合わせて Shift-JIS (cp932) が使われることが多いです。

Python 2 では zipfile モジュールが返すファイル名はバイト文字列だったのでそのまま cp932 のファイル名が返ってきたのですが、 Python 3 では文字列が Unicode に統一されたため、 zip ファイルを読み込むとファイル名がデコードされて文字列になって返ってきます。
が、もちろん日本語の慣習がデフォルトの挙動になってるわけではないので、このままでは文字化けしてしまいます。

Python 3.4 の zipfile モジュールを読むと次のようになっていました。

            if flags & 0x800:
                # UTF-8 file names extension
                filename = filename.decode('utf-8')
            else:
                # Historical ZIP filename encoding
                filename = filename.decode('cp437')

cp932 でエンコードされた文字列をデコードして、 UnicodeDecodeError が起きないでしょうか。

>>> len(bytes(range(256)).decode('cp437'))
256

cp437 は全てのバイトを1文字に1対1でデコードするようです。
ということで、一旦 cp437 でエンコードしなおしてから改めて cp932 でデコードすれば良さそうです。

import zipfile
zf = zipfile.ZipFile('foo.zip')
for name in zf.namelist():
    print(name.encode('cp437').decode('cp932')
55
46
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
55
46

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?