Unicode波型問題 CP932とShift_JISは同じエンコーディングではない

「〜」の文字コードShift_JISで'\x81\x60'で、CP932でも同じコードです。

が、Unicodeには、「波型」と「全角ティルダ」という二つの異なる「〜」が存在します。一般的には「波型」であるu'\u301c'が使われます。Shift_JISの「〜」'\x81\x60'はUnicodeの「波型」にマップされています。

'\x81\x60'.decode('SJIS') == u'\u301c'

「全角ティルダ」のu'\uff5e'は使われない文字なのかと思いきや、

'\x81\x60'.decode('CP932') == u'\uff5e'

Windowsのネイティブ文字コードセットであるCP932(Shift_JISをベースとした独自拡張)では、「〜」'\x81\x60'はUnicodeでいうと「全角ティルダ」u'\uff5e'にあたるそうです。この点において、CP932はShift_JISと互換性のある文字エンコーディングではありません。

CP932はちょっと変わったエンコーディングで、こんな特性があります。

u'\u301c'.encode('CP932') == u'\uff5e'.encode('CP932') == '\x81\x60'
'\x81\x60'.decode('CP932') == u'\uff5e'

うへ! 恒等変換じゃない。
u'\uff5e'はShift_JISにマッピングできないので注意。

u'\u301c'.encode('SJIS') #これはOK
u'\uff5e'.encode('SJIS') #これはNG

#UnicodeEncodeError: 'shift_jis' codec can't encode character u'\uff5e' in position 0: illegal multibyte sequence

ややこしや

Windowsから入ってきた正体不明の日本語テキストは、CP932で解釈してからSJISで保存すると素性のいいものになるかも。

regular_japanese_text =
    untrusted_unicode.encode('CP932').decode('SJIS')