俺のメモ帖

とあるインフラ系SEのメモ帖。趣味や技術的なもとか書けたらいいなぁ。

【Java】Javaの仕様書のShift-JISコードって記載に注意

Windowsで使われているおなじみの文字コード「Shift-JIS(SJIS)」。

だが、実は厳密にはShift-JISではなかったので、軽くはまった件。

 

知ってる人なら、なんだ今更的なことなんだろうけど。

実はWindowsで使われてるのは厳密には「SJIS」ではなく「Windows-31j(MS932もしくはCP932)」という別物の文字コードセットだったということ。

 

以下のような処理を作っていた時の話だ。

  1. 画面から文字を入力。
  2. byte配列に変換して、ホストへ送信。
  3. ホストはbyte配列をデコードし、内容をチェックして、問題なければデータを検索し、検索結果をもどす。
    認識できない文字が存在していると、エラーコードと認識できない文字自体をエラーメッセージに設定して再度Byte配列として返す。
  4. 返却された処理結果をSJISに戻して、PDFに変換して表示する。
    エラーメッセージが含まれている場合は、byte配列をSJISに戻して、画面にエラーメッセージとして表示する。

 

もうなんてことない単純な処理ですね。

ところが、システムではいくつか独自の外字が使用されていた。

また、機種依存文字は許可されない仕様だった。

そこの考慮がされていなかった。

 

そのため、以下の異常動作が発生した。

  1. 外字を入力すると、文字列 <=> Byte配列 の変換を行う際に、変換時に例外が発生する。
  2. エラーメッセージをSJISに戻すと、機種依存文字が??となってしまう。

文字コードの差を知らなかったため、コードを見てもどこにも変な箇所がない。
で、外字に関して調べたんだけど、そこで以下を知る。

  • 外字エリアって、SJISだと文字列として認識できる範囲外に登録されている。
  • Windowsで使われているのはSJISといいつつ、実はMSがSJISを独自拡張したWindows-31Jという文字コードだった。

くわしくはこのページあたり見てもらえれば。

[Java] シフトJISの扱い - Qiita

このため、外字がSJISでは実は扱えないことを知る。

 

今までそんなこと全く知らなかったわ・・・。

C#(.NET Framewrok)ではGetEncodingで使える文字コードセットは、SJIS=MS932=CP932=Windows-31Jで定義されてるようで、こっちは差がないっていうね。
というか、逆に.NET だと純粋なSJISでは扱えないってことらしい。
これ、問題にならないのかね?

 

代表的な文字としては、「髙」とかですかね。
うちの社員にもこの字使う人います。ついでに、システムではこれ外字としても登録されていたっていうね。パッと見、外字なのか機種依存文字なのかわからんので、さらにややこしかった。

 

結果として、エンコード・デコードを行ってる箇所で指定してある「SJIS」を全部「Windows-31j」書き換えることで解決した。

 

今回のような経験がないとおそらくこういう知識増えないんだろうな。
だから仕様書書いた人も全く疑問持たずにSJISって書いてたんだろうな。。。

今度社内でナレッジとして共有しよう。

 

プログラマのための文字コード技術入門 (WEB+DB PRESS plus) (WEB+DB PRESS plusシリーズ)

プログラマのための文字コード技術入門 (WEB+DB PRESS plus) (WEB+DB PRESS plusシリーズ)