PythonでアーカイブしたZIPファイル名をShift-JISにする

Pythonのzipfileライブラリはファイル名をUTF-8でエンコードするためWindowsのレガシーな解凍ソフトで解凍するとファイル名が文字化けします。ファイル名をShift-JISでエンコードする方法を紹介します。

世の中にはUTF-8で文字化けする解凍ソフトが残っている

2007年9月にZIPの仕様が追加され、エンコードをUTF-8に統一するための仕組みが完成してから、ZIPファイル名はUTF-8にエンコードすることがスタンダードになりつつあります。

APPNOTE - PKZIP & SecureZIP

しかし、日本国内では、UTF-8に未対応の解凍ソフト(+Lhaca Lhaplusなど)が大量に出回っており、使用されています。(WindowsのエクスプローラーだけでUTF-8のZIP解凍できるのに)

ファイル名をShift-JISでエンコードできるのか

各UTF-8未対応の解凍ソフトをアンインストールしてもらうわけにもいかないので、ファイル名をShift-JISでエンコードする方法を考えます。

まず、CPythonのzipfileライブラリのソースコードを見てみます。

python/cpython
The Python programming language. Contribute to python/cpython development by creating an account on GitHub.

CPython3.7では、454行目にファイル名のエンコードの関数があります。抜粋すると下記の通り。

 def _encodeFilenameFlags(self): try: return self.filename.encode('ascii'), self.flag_bits except UnicodeEncodeError: return self.filename.encode('utf-8'), self.flag_bits | 0x800

まずASCIIでのエンコードを施行して、UnicodeEncodeErrorならば(=ASCIIでなければ)「UTF-8」でエンコードするようにハードコードされていました・・・

標準ライブラリをコピーしてShift-JISに変更する

あまりしたくないですが・・・標準ライブラリをコピーしてShift-JISに対応します。
454行目の'utf-8''cp932'に変更します。また、フラグ0x800を削除します。

ちなみに、0x800は、ZIPの規格で定められた「general purpose bit flag」のBit 11を1にしています(16進数800=2進数 100000000000)。これは、前述のエンコードをUTF-8に統一するための仕組みで、規格では「Language encoding flag (EFS). If this bit is set, the filename and comment fields for this file MUST be encoded using UTF-8.」と定められており、UTF-8でなければ立ててはいけないフラグなので取り除いています。

https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT

zipfile.py

python/cpython
The Python programming language. Contribute to python/cpython development by creating an account on GitHub.
454-: return self.filename.encode('utf-8'), self.flag_bits | 0x800 454+: return self.filename.encode('cp932'), self.flag_bits

import先を今回作ったzipfile.pyに変更します。

from .zipfile import ZipFile (略) with ZipFile(zb, mode='w') as zf: (略)

以上の対策で、Windowsのレガシーな解凍ソフトで解凍できるようになります。逆にLinuxなどではUTF-8しか対応していないため文字化けする可能性があります。

プログラミング
この記事を書いた人
まっしろ

お家とインターネットが大好きな20代社会人です。
眠らない街渋谷に住んでいますが、平均睡眠時間は9時間です。
在宅勤務でWebサービスのフロント・バックエンドエンジニアをしています。

フォローする
スポンサーリンク
まっしろブログ

コメント