misc.log

日常茶飯事とお仕事と

文字コードについて調べなおす機会があったのでメモ

PHPのプログラムで、Cookieの文字列がSJISで指定されていて、受け側が全部UTF-8で死ぬという事件がありいろいろ調べつつ対応(笑)

この辺、いつも調べながら「なんだっけ?」って思い出しているので、チェックのポイントだけメモっておきます。

UTF-8にしかない文字

扱える文字の種類はUnicodeであるUTF-8の方が圧倒的に多いので、UTF-8では入力、表示できても、SJISに対応する文字が無いことがあります。このあたりの文字でいったい何が起きるか、というのは文字を扱うシステムではチェックする必要がありますね。

たとえば

  • ほっけ(魚へんに花)
  • よう(目+華)
  • つかむ(てへんに國)
  • おう(森鴎外のおう、難しい方)

などです。これらについてはSJISに変換した時点で文字化けしますが、「文字化け後、何バイトになるか?」にも留意する必要があります。たとえばデータベースに格納する場合、文字化けしても登録できればエラーにはなりませんが、桁数オーバーしてしまうとエラーです。
特に、Unicodeサロゲートペア文字(2文字分のコードで1文字を表現するタイプの文字)は、文字化け後も2文字とかになることがあるので注意が必要です。

SJISの拡張文字

SJISもいろんな拡張やこれまでの歴史的経緯で関係各社が追加した文字があるようです。詳しくは正直把握しきれていないのですが、少なくとも業務システムでありがりな「人名」などに関すると思われる文字が「IBM拡張文字」というカテゴリに含まれています。このあたりの文字を入力したり、参照したりした場合にどうなるか、という点もチェックする必要がありますね。

髙 閒 塚 德 﨑 彅 弴 燁 珉 鄧

PHP:mb_convert_encodingの取り扱い

第3引数の「変換元文字コード」を「auto」に指定した場合に、うまく変換できない(エラーになる)ケースがありました。たしか「㈱」(括弧付きの株)などだったかと。これを回避するには、明示的に変換元を指定する必要があるようです(他に良い手があるかもしれませんが、ちょっと調べきれませんでした)。

この時、変換元の文字種が複数あり得る場合は、mb_detect_encodingで文字コードの判定をしてから処理を分けるとよいでしょう。ただ、この場合も文字コード名が取れない文字があったので要注意です。たしか「㈱」や「髙」でした。おそらくですが、自動判定の場合には「SJIS-Win」は選択されないのかもしれません。この㈱や髙はSJIS-winに含まれる文字なので、判定不能になってしまったのかもしれません(括弧付きの株はJIS X 0213:2004に登録されているIBM拡張文字)。