路傍のプログラマ

只のプログラマが綴る愚痴と備忘録

OSXで作ったzipをWinで解凍するさらにもう一つの方法 (Python)

2007-06-14 11:52:12 | プログラミング
Macで作ったzipファイルを解凍しようとするとファイル名が文字化けしてしまいます、みたいな問題が未だに絶えない昨今。

原因は割と単純で、OS Xが作るzipファイルは、ファイル名がutf-8でエンコードされて格納されるのに対して、WindowsはシフトJIS(より正確にはCP932)でエンコードされているからです。

フリーソフトを使った解決策もあるようですが、ここはひとつプログラマ的な解決策として、Pythonでやってみます。

以下の例では、OSXで作ったzipファイル(中身のファイルは「ほげテキスト.html」)をVista上でPythonのインタラクティブシェル(IDLE)で解凍します。

まず、必要なモジュールをインポートしておきます。

>>> import os
>>> import zipfile
>>> import unicodedata

zipファイルがあるディレクトリに移動し、zipファイルの名前を調べます。

>>> os.chdir(r'C:temp')
>>> os.listdir('.')
['mandel.py', 'x82xd9x82xaf_x83ex83Lx83Xx83g_html.zip']

2つめのファイルがOSXで作ったzipファイルです。
このzipファイルを開いて、格納されているファイルの名前を調べます。

>>> zf = zipfile.ZipFile('x82xd9x82xaf_x83ex83Lx83Xx83g_html.zip', 'r')
>>> names = zf.namelist()
>>> print names
['xe3x81xbbxe3x81x91xe3x82x99xe3x83x86xe3x82xadxe3x82xb9xe3x83x88.html']

ここで、ファイル名のエンコーディングを変更するための関数(utf-8を正規化してからシフトJISに直す関数)を定義しておきます。

>>> def decu8(s): return unicodedata.normalize('NFC', unicode(s, 'utf-8')).encode('Shift_JIS')

この関数を使って、格納されているファイルの名前を印字してみます。

>>> print decu8(names[0])
ほげテキスト.html

後は、格納されているファイルのバイト列を取り出して、ファイルに保存すればOKです。

>>> f = file(decu8(names[0]), 'wb')
>>> f.write(zf.read(names[0]))
>>> f.close()

後始末として、zipファイルを閉じておきます。

>>> zf.close()

この辺がささっとできるのは、さすがスクリプト言語ですね。

逆(Win → OSX)も、やってませんが、多分、簡単にできることかと。