今日は,みなさんに重要なお願いがあります.
Java 2 SDK 1 2から"Shift_JIS"のエイリアスがSJISコンバータからMS932コンバータに変更されましたが,IANAのcharset定義を正しく実装するため,および現在J2EE分野で発生している文字化け問題の対策として,Java 2 SDK 1.4.1β版から再び元に戻すことになりました. これについては,次のバグレポートをお読みください.
Follow the IANA definition for "shift_jis" charset name
http://developer.java.sun.com/developer/bugParade/bugs/4556882.html
"As part of the introduction of newly implemented (using NIO cs API) charset support in Hopper we are reappraising the aliases attributed to the various supported encodings. This particular change will be effected for 1.4.1 beta."
「Hopper(1.4.1)で(NIOの文字集合変換APIを用いて)新しく実装されたcharsetサポートの導入と共に,私たちはサポートされているさまざまな文字エンコーディングへのエイリアスを再検討しています. これに関する変更は,1.4.1β版から有効になるでしょう.」
ただし,日本のJava開発者がこの修正に反対してしまうと,この話は流れてしまうかもしれません.
そこで,今回の変更の主旨と,みなさんのプログラムに与える影響を説明します. ご面倒ですが,この記事を読んで頂くと共に,知人や関連部署などにも,この投稿の内容を理解して頂くように協力をお願いします.
なお,この投稿と同じ内容をhttp://www.ingrid.org/java/i18n/encoding/shift_jis.htmlで公開しますが,ここでは他に実装のチェックやFAQなどの情報も掲載していく予定です.
最後に,このような文字コードの問題は複雑であり,なかなか完全無欠の回答というものはありません. しかし,問題を放置して永久に苦しみ続けるより,一時的な移行のコストを払っても,将来的に問題から開放される方向に努力していきましょう.
風間一洋 (kazama@ingrid.org) NTT未来ねっと研究所
"Shift_JIS"と"Windows-31J"は,IANAに正式に登録されている文字集合の名称であり,前者はJIS X 0208で定められており,後者はMicrosoftのコードページ932に相当します. この2つの文字集合には,次のような重要な違いがあります.
特に最後の違いがあるために,JavaのようなUnicodeベースの環境では,単純にWindows-31JをShift_JISのスーパーセットとして扱うことはできないことに注意してください.
1.1がリリースされた当初は,"Shift_JIS"はSJISコンバータにエイリアスされていました. しかし,Windows-31Jがサポートされていないために,NEC特殊文字などが表示できない,Unicodeのマッピングが違う記号類が文字化けするなどの問題が生じてしまいました.
そこで,日本のJava開発者から,Windows-31Jもサポートして欲しいという要求が出され,それが受け入れられて,1.1.8と1.2からMS932コンバータが追加され,日本語Windows環境のデフォルトも変更されることになりました.
ただし,この時に"Shift_JIS"がSJISコンバータからMS932コンバータへのエイリアスの変更もおこなわれてしまいました. これは,"Shift_JIS"と宣言しながら,実際にはWindows-31Jを用いている場合があったことや,そして従来各社が用いてきたShift-JISを独自に拡張した文字集合のコンバータを個別に追加するかわりに,当面はMS932コンバータで代用しようと考えたからのようです.
もちろん,これを元に戻して欲しいという要望も出しましたが,当時は受け入れられませんでした.
今回,この変更が再考されることになったのは,XMLやWebアプリケーションなど,推奨MIME名を用いなければならないアプリケーション分野の拡大に伴って,利点より欠点の方が深刻になりつつあることが再認識されたからです.
"Shift_JIS"からMS932へのエイリアスが引き起こす問題は,次の通りです.
具体的な例を挙げれば,後者の問題に関しては,たとえばServletでは次のような回避コードが使用されてきました.
res.setContentType("text/html; charset=Shift_JIS");
PrintWriter out =
new PrintWriter(new OutputStreamWriter(res.getOutputStream(),
"SJIS"));
また,XMLパーサ"Xerces-J"のように,Shift_JISとSJISコンバータの正しいマッピングを自前で実装して回避していることもあります.
しかし,JavaServer Pagesでは,"SJIS"は推奨MIME名ではないことを無視して,次のようにせざるを得ません.
<%@ page contentType="text/html; charset=SJIS" %> (注: このコードは本当は誤りです)
1.4からは,推奨MIME名を用いていく方針になり,java.nio.charset.Charset.isRegistered()というメソッドでこの正当性を容易にチェックできるので,近い将来に,この方法も使えなくなりそうです.
つまり,このままではJavaで"Shift_JIS"と"Windows-31J"を使い分けていくことも不可能になるかもしれません.
今回の修正の影響範囲と対処方法は,次の通りです.
a) Servletの場合
res.setContentType("text/html; charset=Windows-31J");
PrintWriter out = res.getWriter();
b) JSPの場合
<%@ page contentType="text/html; charset=Windows-31J" %>
名前: Shift_JIS (推奨MIME名)
MIBenum: 17
典拠: この文字集合は,csHalfWidthKatakanaに,JIS X 0208の図形文字を追加
した拡張です.このCCSは,JIS X0201:1997とJIS X0208:1997です.
完全な定義は,JIS X0208:1997の付録1で見ることができます.
この文字集合は,トップレベルのメディアタイプ"text"に使用できます.
エイリアス: MS_Kanji
エイリアス: csShiftJIS
名前: Windows-31J
MIBenum: 2024
典拠: Windowsの日本語です.Shift_JISに,NEC特殊文字 (13区),NEC選定IBM
特殊文字 (89区〜92区), IBM特殊文字 (115区〜119区)を含めた拡張です.
このCCSは,JIS X0201:1997,JIS X0208:1997および上記の拡張です.
この文字集合は,トップレベルのメディアタイプ"text"に使用できますが,
限定された用途,または特殊用途に用います (RFC2278参照).
PCL記号セット ID: 19K
エイリアス: csWindows31J