ソフトウェアなどを使いこなすために、ストレスを感じながらもしぶしぶ覚えなければならないようなノウハウ、「 バッドノウハウ」がテーマの本連載、最終回の今回は文字コードのBKを取り上げたいと思います。
文字コードとバッドノウハウ
文字コードは、Web開発を行う上で避けては通れない分野です。文字化けを起こさずに、コンテンツをブラウザに正しく表示させることはWeb開発の基本といえます。
しかしながら、文字コードには歴史的な紆余曲折がいろいろあり、膨大なバッドノウハウが人類の英知として蓄積されています。今回は、その膨大なるBKの一部を紹介したいと思います。
機種依存文字は滅びず
文字コードのBKといえば、機種依存文字の存在を忘れてはなりません。インターネットの世界では、古くから「①などの丸付き数字は機種依存文字だから使うな」といわれています。これらの文字はその昔「NEC特殊文字」と呼ばれ、Macとの相性が悪いことで知られていました。たとえば、「 ①」が含まれるテキストファイルをWindowsで作ってMacで開くと「(日)」と表示されるといった具合です[1] 。
この問題は最近ではどうなったのかと思い、調べてみました。まず、丸付き数字① ② ③を含むページをCP932という文字コード [2] で保存し、Macのブラウザで表示してみました。その結果、Firefox、Safariとも、問題なく丸数字を表示できました(図1・注3 ) 。幸いなことに、最近のMacのブラウザではこの問題は解決しているようです。
図1 無事に表示されました
次に、丸付き数字①②③を含むメールをISO-2022-JP[4] という文字コードで送信し、MacのMailで受信してみました[5] 。結果はなんと...(図2 ) 。
図2 見事に文字化け
見事に文字化け。機種依存文字という言葉は最近あまり聞かなくなりすでに克服されていると思っていたのですが、まだまだ健在のようです。
絵文字をめぐる混乱
携帯電話の世界では欠かせない絵文字、これも機種依存文字の一種といえます。各キャリアごとに使える絵文字が異なり、使われている文字コードも異なります。たとえば、太陽の絵文字を各キャリアのShift_JIS[6] で扱うにはDoCoMoの場合F89F、auの場合F660、SoftBankの場合F98Bというコードになります[7] 。
さらに厄介なことに、SoftBankの一部の絵文字は「IBM拡張文字」との互換性にも問題があります。たとえば、名字に使われる「瀨」という文字はCP932ではFB50というコードが割り当てられていますが、SoftBankのShift_JISではFB50はショックを受けた顔文字になります(図3・注8 ) 。
図3 瀨戸のホームページ! のはずが...
これらの混乱のため、ネット上には絵文字に関する膨大なBKが蓄積されています。PerlのEncode::JP::Mobileといった相互変換ライブラリや、Six Apartの自由に使える絵文字アイコン画像 といった先人の成果により、絵文字の扱いはだいぶ楽になりつつあります。
また、最近ではUnicodeの専門家等によるemoji4unicodeプロジェクト が発足し、絵文字をUnicodeに追加する計画が進行しています。絵文字の混乱を鎮めるためにはまだまだ多くの労力が必要そうです。
絵文字の登場により、機種依存文字の悪夢が再びやってきた、といった感じでしょうか。
Macのファイル名とNFD
最近では、UTF-8を使ったWebサイトが主流になってきました [9] 。筆者が扱うテキストデータは、最近ではほとんどUTF-8です。いろいろな文字コードのデータが混在していた頃と比べると、ずいぶんシンプルになりました。
とはいえ、UTF-8にすれば、すべてシンプルになるかといえば、そうでもありません。たとえば、Mac OS Xではファイル名にUTF-8を用いていますが、Normalization Form D(NFD)という正規化が行われているため要注意です(注10 。
たとえば、「 が.txt」というファイルをMac OS Xで作ると、ファイル名は「\xe3\x81\x8b\xe3\x82\x99.txt」のようにエンコードされます。Pythonで簡単に確認できます(図4 ) 。
図4 Pythonで確認
% python
>>> import os
>>> os.listdir(".")
['\xe3\x81\x8b\xe3\x82\x99.txt']
通常、「 が」はUTF-8でエンコードすると「\xe3\x81\x8c」という1つのコードになりますが、NFD形式では「\xe3\x81\x8b」と「\xe3\x82\x99」という2つのコードに分解されています。
このため、「 が.txt」という名前のファイルを見つけるには、文字列をNFD形式に正規化した上で比較する必要があります。Pythonの場合、NFD形式への正規化はunicodedataモジュールで行えます(リスト1 ) 。
リスト1 Pythonで、NFD形式への正規化
import unicodedata
import os
# NFD 形式に正規化
target = unicodedata.normalize(
'NFD', '\xe3\x81\x8c.txt'.decode('utf-8'))
for file_name in os.listdir('.'):
if file_name.decode('utf-8') == target:
print 'found'
本連載の前回「ブラウザのバッドノウハウ<コンテンツ編>」でも述べたように、日本語のファイル名は永遠のBKのテーマです。
まとめ
今回は、文字コードに関するバッドノウハウを紹介しました。文字コードの世界にはほかにも「波ダッシュと全角チルダ」「 サロゲートペアとMySQL」「 冗長なUTF-8とセキュリティホール」などなど、今回取り上げなかったBKが渦巻いています。興味のある方は、ぜひ調べてみてください。
一年間、6回にわたってバッドノウハウについて書きました。BKの背後には何かしらの理由があり、それらの教訓から学ぶことは、ソフトウェア開発を学ぶ上で大切なことではないかと思います。本連載が読者のみなさまにBKのおもしろさを伝えることができれば幸いです。