- PR -

Servletでの文字コード問題

投稿者投稿内容
(株)ぽち
ぬし
会議室デビュー日: 2002/09/10
投稿数: 376
投稿日時: 2003-05-21 12:59
お世話になっております。

文字コード関連にはあまり知識がなく、以下のような問題に悩んでいます。

[問題]
 あるプログラム(WEBアプリ)を他の環境に移行した際
 もともと正常に文字を処理していたものが、移行した
 環境で文字化けを起こすようになった。
 #文字化けを起こす文字は@、Tなどの機種依存文字です。

このようなケースは多いと思うのですが、不可解な点があります。

もともと開発していた環境は以下です。
OS:WinXPpro
JDK:1.4.1_01
APサーバ:weblogic7.0
DB:oracle8.1.6

移行した環境は以下です。
OS:Win2000server
JDK:1.4.1_01
APサーバ:weblogic7.0
DB:oracle8.1.6

OS以外は全く同一であり、OSもwindowsというレベルで同一です。

なのになんで文字化けが発生するのでしょうか?
ちなみに、webの画面はcharset=Windows-31Jで定義しています。

解析した結果は以下です。
・Servletで文字列を取得した時点で文字化けを起こしている。

リクエストから文字列を取得し、ダンプしてみました。
[正常環境]
 @:[2460]

[異常環境]
 ?:[fffd]
 @:[40]

文字列ダンプに使用した関数は以下のようなものです。
コード:
public static void dump_16(String s) {
 int hex;
 for( int i=0; i<s.length(); ++i ){
  hex = (int)s.charAt(i);
  System.out.println(s.charAt(i) + ":[" + Integer.toHexString(hex)+ "]");
 }
}



なぜ同じwindows環境でこのような現状が起こるのでしょうか?
Kissinger
ぬし
会議室デビュー日: 2002/04/30
投稿数: 428
お住まい・勤務地: 愛知県
投稿日時: 2003-05-21 21:49
(株)ぽちさん、こんにちは。

確かに不可解ですね。
問題を起こしているほうは UTF-8のコンバータが動いちゃってるようにも見えます。

サーバ側はOSのみが違うとの事ですが、クライアントは同じ物でしょうか?

問題がサーバ側にあるのか、クライアント側なのか切り分けしてみる必要があるかも知れません。
試しに javax.servlet.HttpRequestのgetReader()の代わりにgetInputStream()でデータをバイナリのまま読込むようにして、問題のあるものと無いものを比較してみてはどうでしょうか?

バイナリが同じなら、サーバ側のエンコーディングの問題でしょうし、違えばクライアントの設定等の違いかも知れません。

(株)ぽち
ぬし
会議室デビュー日: 2002/09/10
投稿数: 376
投稿日時: 2003-05-22 09:32
引用:

Kissingerさんの書き込み (2003-05-21 21:49) より:
(株)ぽちさん、こんにちは。

確かに不可解ですね。
問題を起こしているほうは UTF-8のコンバータが動いちゃってるようにも見えます。

サーバ側はOSのみが違うとの事ですが、クライアントは同じ物でしょうか?



Kissinger様、ありがとうございます。

クライアントに関しては、全く同一のものを使用していまして
WindowsXPHomeでIE6.0です。

おそらくサーバに問題があるとは思います。

また、コンバータが違う文字コードのコンバータを使用しているかも、
とのことで次のことを試しました。

String xx = new String(対象文字.getBytes("8859_1"), "文字コード")

文字コードの箇所を色々いじって出力してみました。

===
JISAutoDetect :
?:[3f]
@:[40]

SJIS :
?:[3f]
@:[40]

Shift_JIS :
?:[3f]
@:[40]

EUC-JP :
?:[3f]
@:[40]

JIS :
?:[3f]
@:[40]

MS932 :
?:[3f]
@:[40]


何をやってもダメみたいでした。

UTF-8のコンバータが使用されているとして
機種依存文字等の文字を正しく変換させることは不可能なのでしょうか?
(株)ぽち
ぬし
会議室デビュー日: 2002/09/10
投稿数: 376
投稿日時: 2003-05-22 10:31
お世話になります。

最初に環境の差異はOSのみだ、と言いましたが
よくよく考えてみると他に大きな差異がありました。

開発環境上にのっているweblogicは実行java環境
としてJDK1.3.1を使用していました。

試験環境のweblogicはJDK1.4.1を使用しています。

JDK1.4.1を使用するのが適切な環境です。

この場合、JDKのバージョンによるコンバータの差異等
はあるのでしょうか?

latte
常連さん
会議室デビュー日: 2002/11/07
投稿数: 38
投稿日時: 2003-05-22 10:37
JDK1.4.1で文字コードの扱いに変更が入っています。
http://java.sun.com/j2se/1.4.1/ja/changes.html#Shift-JIS
を参照されてみては如何でしょうか。
(株)ぽち
ぬし
会議室デビュー日: 2002/09/10
投稿数: 376
投稿日時: 2003-05-22 11:03
引用:

latteさんの書き込み (2003-05-22 10:37) より:
JDK1.4.1で文字コードの扱いに変更が入っています。
http://java.sun.com/j2se/1.4.1/ja/changes.html#Shift-JIS
を参照されてみては如何でしょうか。



回答ありがとうございます。

実はそのことについては調べていまして、
要はShift_JISは使うな、という意味だと解釈しました。

そこで@ITでもいつかの記事であったのですが
Windows-31Jを指定するべきだ、とのことから
今回はjspのpageディレクティブにてwindows-31jを指定しています。

このようにすればMS932として解釈してくれるのかな、と思いました。

色々試してみて解析してみます。

何か情報があればお願い致します。
山本 裕介
ぬし
会議室デビュー日: 2003/05/22
投稿数: 2415
お住まい・勤務地: 恵比寿
投稿日時: 2003-05-22 11:36
こんにちは。

getParameter() で取得する際に用いるエンコードは weblogic.xml で指定できますよ。

↓こちらに詳しくかかれています。
・文字化け“???”の法則とその防止策
http://www.atmarkit.co.jp/fjava/rensai2/webopt08/webopt08.html

・WebLogic Server 7.0 SP2 日本語環境での使用にあたって
http://edocs.beasys.co.jp/e-docs/wls/docs70/ja/index.html
・日本語環境での使用にあたって
http://edocs.beasys.co.jp/e-docs/wls/docs81/ja/index.html

あと、Weblogic7.0では JDK1.4.1 は使えないと思います。
http://edocs.beasys.co.jp/e-docs/wls/certifications/certifications/win2000.html#59067

JDK1.4.1を使うのが必須要件なら最新の Weblogic8.1 を使ってみてはいかがでしょう?
・WebLogic8.1
http://edocs.beasys.co.jp/e-docs/wls/docs81/index.html

解決しないようでしたらサポートも利用してはいかがでしょう?せっかく高級なサーバ使ってるわけですから。なにかわかったら教えてくださいね。
(株)ぽち
ぬし
会議室デビュー日: 2002/09/10
投稿数: 376
投稿日時: 2003-05-22 13:25
インギ様

回答ありがとうございます。

ページを見させていただきました。

とりあえず、現状の状況を言いますと

[JDK1.3.1にすれば?]
 すでに開発も終盤ですので、今更変更するわけにもいかず・・。

[weblogic8.0にすれば?]
 実は使用しているweblogicは試用版でして。。
 まぁ色々事情はあるのですが。実際にアプリを乗せる
 サーバは別の製品なのです。その辺はお察しください・・。

 ですので当然サポートも受けることはできず。


結局色々ページ見ながら試していたら解決しました。
上記でも言ったようにweblogicはあくまで動作確認用サーバですので
あまりweblogic固有の設定で解決したくはありませんでした。

で、以下の方法で解決してしまいました。

・servlet内に以下のコードを記述
 request.setCharacterEncoding("MS932");

なぜこれで解決したのかは不明です。

以前にも試しましたが
String xx = new String(文字.getBytes("8859_1"), "MS932");
というやり方ではダメでした。

この二つの方法に何か違いがあるのでしょうか。
私は同じことをやっているんだと思っていたんですが。。
 
まだわからんないことがあるので色々調べて見たいと思います。

スキルアップ/キャリアアップ(JOB@IT)