Windowsで使われているおなじみの文字コード「Shift-JIS(SJIS)」。
だが、実は厳密にはShift-JISではなかったので、軽くはまった件。
知ってる人なら、なんだ今更的なことなんだろうけど。
実はWindowsで使われてるのは厳密には「SJIS」ではなく「Windows-31j(MS932もしくはCP932)」という別物の文字コードセットだったということ。
以下のような処理を作っていた時の話だ。
- 画面から文字を入力。
- byte配列に変換して、ホストへ送信。
- ホストはbyte配列をデコードし、内容をチェックして、問題なければデータを検索し、検索結果をもどす。
認識できない文字が存在していると、エラーコードと認識できない文字自体をエラーメッセージに設定して再度Byte配列として返す。 - 返却された処理結果をSJISに戻して、PDFに変換して表示する。
エラーメッセージが含まれている場合は、byte配列をSJISに戻して、画面にエラーメッセージとして表示する。
もうなんてことない単純な処理ですね。
ところが、システムではいくつか独自の外字が使用されていた。
また、機種依存文字は許可されない仕様だった。
そこの考慮がされていなかった。
そのため、以下の異常動作が発生した。
文字コードの差を知らなかったため、コードを見てもどこにも変な箇所がない。
で、外字に関して調べたんだけど、そこで以下を知る。
- 外字エリアって、SJISだと文字列として認識できる範囲外に登録されている。
- Windowsで使われているのはSJISといいつつ、実はMSがSJISを独自拡張したWindows-31Jという文字コードだった。
くわしくはこのページあたり見てもらえれば。
このため、外字がSJISでは実は扱えないことを知る。
今までそんなこと全く知らなかったわ・・・。
C#(.NET Framewrok)ではGetEncodingで使える文字コードセットは、SJIS=MS932=CP932=Windows-31Jで定義されてるようで、こっちは差がないっていうね。
というか、逆に.NET だと純粋なSJISでは扱えないってことらしい。
これ、問題にならないのかね?
代表的な文字としては、「髙」とかですかね。
うちの社員にもこの字使う人います。ついでに、システムではこれ外字としても登録されていたっていうね。パッと見、外字なのか機種依存文字なのかわからんので、さらにややこしかった。
結果として、エンコード・デコードを行ってる箇所で指定してある「SJIS」を全部「Windows-31j」書き換えることで解決した。
今回のような経験がないとおそらくこういう知識増えないんだろうな。
だから仕様書書いた人も全く疑問持たずにSJISって書いてたんだろうな。。。
今度社内でナレッジとして共有しよう。
プログラマのための文字コード技術入門 (WEB+DB PRESS plus) (WEB+DB PRESS plusシリーズ)
- 作者: 矢野啓介
- 出版社/メーカー: 技術評論社
- 発売日: 2010/02/18
- メディア: 単行本(ソフトカバー)
- 購入: 34人 クリック: 578回
- この商品を含むブログ (129件) を見る