2011年3月3日木曜日

PHPの SJISと SJIS-WINの違い


SJIS-WINとは?

PHPで文字コードとして「SJIS-WIN」を指定すると、Microsoftが拡張したShift_JISであるWindows-31Jが使われる。

Windows-31Jは、Microsoftが「JIS X 0208-1990」をベースに、NECとIBMの独自拡張文字の一部(一般的にはSJISの「機種依存文字」と呼ばれる?)を取り込んだ文字コード。
(参考:Microsoftコードページ932 - Wikipedia



SJISとSJIS-WINで何が違うの?


SJIS-WINの方が文字が多い。

よく使うところでは、下記のような文字はSJISーWINにはあるがSJISにはない。

  • 丸数字 (①②③...⑳)
  • ローマ数字 (ⅠⅡⅢ...Ⅹ、ⅰⅱⅲ...ⅹ)
  • カッコ付きの株 (㈱)
  • はしご高[はしごたか] (髙)
  • たつ崎[たつさき、たちさき] (﨑)



SJIS-WINにはあるがSJISにはない文字

下記の3種類
  • NEC 特殊文字(13区)
  • NEC 選定 IBM 拡張文字(89~92区)
  • IBM 拡張文字(115~119区)

具体的な文字の一覧については下記参考サイトを参照。



SJIS-WINにはあるがSJISにはない文字を正規表現で探すには?

preg_match()等のPCRE関数はUTF-8以外のマルチバイト文字に対応していないので、そのままではShift_JISには使えない。(UTF-8の場合はパターン修飾子として"u"を付ければ使える。)
一見Shift_JISでも使えそうに見えることもあるが、Shift_JISの2バイト目と次の文字の1バイト目を1つの文字とみなしてヒットしてしまう場合がある。
preg_match('/[\x87][\x40-\x8F]/', 'ョ@'); // => true

対策としては、対象文字列をmb_substr()等を使いあらかじめ1文字ずつに分解しておいて、それを1文字ずつチェックしていけば正しく判定できる。

また、PHP4ではmb_ereg系の関数をこれに使えたみたいだが、鬼車のPHP5では使えないみたい。

単純にSJIS-WINにはあるがSJISにはない文字を含んでいるかどうかを判定しただけなら、それぞれの文字コードに変換した後に比較すれば分かる。
$utf8 = '株';
$sjis = mb_convert_encoding($utf8, 'SJIS', 'UTF-8');
$sjisWin = mb_convert_encoding($utf8, 'SJIS-WIN', 'UTF-8');

var_dump($sjis === $sjisWin); // => true

$utf8 = '㈱';
$sjis = mb_convert_encoding($utf8, 'SJIS', 'UTF-8');
$sjisWin = mb_convert_encoding($utf8, 'SJIS-WIN', 'UTF-8');

var_dump($sjis === $sjisWin); // => false

0 件のコメント:

ブログ アーカイブ

tags