Java の MS932 エンコーディング の SJIS<->Unicode 対応表と
Oracle Database の JA16SJIS キャラクタセットの SJIS<->Unicode 対応表が異なるため。
例えば、Webアプリにユーザが「〜(0x8160)」を入力すると、Oracle Database に 0x8160 で保存される。
ここまでは無問題。
次に Oracle Database に保存された 0x8160 をWebアプリで表示しようとすると問題が起こる。
Oracle Database は 0x8160 を U+301C に変換して、JVM に渡すが、JVM の Unicode->SJIS 対応表に U+301C は存在しないため「?」となる。
MS932 と JA16SJIS の SJIS<->Unicode 対応表は以下のように異なり、
変換方向 | MS932 | JA16SJIS |
---|---|---|
SJIS → Unicode | 0x8160 → U+FF5E | 0x8160 → U+301C |
Unicode → SJIS | U+FF5E → 0x8160 | U+301C → 0x8160 U+FF5E → 0x8160*1 |
従って、
ブラウザ -- 0x8160
↓
JVM で変換 -- 0x8160 -> U+FF5E
↓
Oracle で変換 -- U+FF5E -> 0x8160
↓
Oracle に保存 -- 0x8160
↓
Oracle で変換 -- 0x8160 -> U+301C
↓
JVM で変換 -- U+301C -> ?
↓
ブラウザ -- ?
という具合にチルダが文字化けする。
この問題を回避するために生まれたキャラクタセットが JA16SJISTILDE。
参考
- 続・門外不出のOracle現場ワザ (DB SELECTION) P.243-244
*1:8.1.6以降