- PR -

文字化け(サーブレット)

投稿者投稿内容
ばっちゃん
会議室デビュー日: 2004/11/01
投稿数: 7
投稿日時: 2004-11-24 20:32
サーブレットで文字列をHTMLから入力してサーブレットに渡して表示させるという簡単なプログラムを作っているのですが、文字化けしてしまいます。文字コードの指定はしているのですが・・・だれかわかる人がいたら教えてください。宜しくお願いします。

/////html////////////
<html>
<head><meta http-equiv="Content-Type" content="text/html; charset=shift-jis">
<title>文字列</title>
</head>
<body>
<form method="Post" action="/TestAp/mojiretu">
検索キーワード:<input type="text" name="q" size="30"><p>
<input type="submit" value="送信">
<input type="reset" value="キャンセル">
</form>
</body>
</html>

////////サーブレットプログラム////////////////
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class mojiretu extends HttpServlet{
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
response.setContentType("text/html; charset=Shift-JIS");
PrintWriter out = response.getWriter();
String br = request.getParameter("q");

out.println("<html><head><title>sen</title></head><body>");
out.println(br);


out.println("</body></html>");
out.close();
}
}

//////////////////////////
山本 裕介
ぬし
会議室デビュー日: 2003/05/22
投稿数: 2415
お住まい・勤務地: 恵比寿
投稿日時: 2004-11-24 21:03
getParameter で受け取った文字列が文字化けする、ってのは一番最初に覚える国際化の掟です。
「サーブレットのいろは」について書いてあるサイトでも良く説明されていると思います。

API をみて国際化に関連するメソッドがないか確認してみましょう。
http://java.sun.com/j2ee/sdk_1.3/techdocs/api/javax/servlet/ServletRequest.html

バクシ
会議室デビュー日: 2004/10/06
投稿数: 12
投稿日時: 2004-11-24 22:46

どのバージョンのサーブレットを使っているかによりますが,つぶしが利くのは,
String br = request.getParameter("q");
br=new String(br.getBytes("ISO-8859-1"), "<エンコーディング>");

です。不思議な構文ですが,おまじないと思ってください。
さて,問題は<エンコーディング>,Shift-JISといっても現実には一筋縄ではいきません。SJIS(=Shift_JIS)とするか,MS932(=Windows-31J)とするか。シフトJIS系にこだわる限り,万能薬はありません。
サーブレットをつかうのであれば,静的なコンテンツも含めてUTF-8に統一するのが正道でしょう。将来を見据えてということもありますが,Javaがユニコードベースなのですから,ユニコード以外を出入力に使おうとすると,どうしても変換テーブルの世話になります。この変換テーブルに種々の問題があることは避けられません。シフトJIS系を棄てられない事情がありますか?
ばっちゃん
会議室デビュー日: 2004/11/01
投稿数: 7
投稿日時: 2004-11-24 23:33
ご返事ありがとうございました。
request.setCharacterEncoding("Shift-JIS");
で文字化け直りました^^ありがとうございましたm(__)m
kito
ベテラン
会議室デビュー日: 2003/03/24
投稿数: 59
お住まい・勤務地: Osaka
投稿日時: 2004-11-25 01:52
引用:

バクシさんの書き込み (2004-11-24 22:46) より:

どのバージョンのサーブレットを使っているかによりますが,つぶしが利くのは,
String br = request.getParameter("q");
br=new String(br.getBytes("ISO-8859-1"), "<エンコーディング>");

です。不思議な構文ですが,おまじないと思ってください。


こんな時代遅れの誤ったコーディングを勧めるのは止めましょう。
どれだけ多くの初心者がこのgetBytes()に惑わされていることか。おまじないってなんですか?
意味を考えたらわかりますが、提示されているのは(仮にsjisとして)
「SJISのバイト列を、誤ってiso-8859-1のバイト列と解釈してUnicodeに変換してしまった文字列」に
対するコーディングです。そんなものを無理やり元に戻そうとするよりも、
最初からデタラメな文字列が生成されないようなコーディングをするべきでしょう。

大昔、多くのフレームワークが国際化を全く考慮していなかった時代なら仕方のない面もあったのでしょうけど、
現在なら、多くのライブラリやフレームワークが国際化に対応しています。
それぞれに最適な手段があるわけですからそれを使いましょう。ドキュメントやWebで調べればたいていは見つかります。

String#getBytes()を他に手が無いときの「最後の手段」として挙げるのならまだましですが
さも一般的な手法であるかのように書いてしまうのは初学者を混乱させるだけです。
takamaro
大ベテラン
会議室デビュー日: 2004/10/12
投稿数: 100
投稿日時: 2004-11-25 03:40
私はWebアプリケーションに関してド素人ですので正確な知識を持ち合わせている訳では
ありませんが、遠目から眺めていた記憶が正しけば java.lang.String#getBytes() を
用いたコーディングは、ServletAPI 2.2に準拠したコンテナ環境では一般的であったと
記憶しております(各ベンダー独自の方法は別にあったにせよ)
これが、特に「誤った」と言われる程の手法ではなかったと思います。
日本語での最初(?)のServlet&JSP解説本「Javaサーバーサイドプログラミング 原田洋子著」
ではTomcat3.2.1が題材として書かれていました(私の手元に在る唯一のServlet本w)
ここでは「唯一の解」としてgetBytes()手法が紹介されています。
もし(あいにく私は知り得ませんが)「最初からデタラメな文字列が生成されないような
コーディング」がこの環境(Tomcat3.2.*)で存在していたならば、日本のServlet界(?)
を牽引してきた原田女史にも大きな責任の一端がある事でしょう(かなり大袈裟ですけどw
そうではなく「ServletAPI 2.3以降に準拠した製品を使うべき」という主旨だけでしたら
「誤った」的な発言は不要な部分ではないかと感じます。
初心者に対して「誤解を与える」とはいいますが、初心者であれ将来的に過去の遺産として
現存する「既存」のアプリケーションのメンテナンスを行なう可能性もあるわけですし、
逆にsetCharacterEncoding()以前のコーディングを理解していないというのも問題がない
とは言えないのではないでしょうか。
時代の流れの中で、将来「知っておく」必要性は薄くなっていくでしょうが、現在が「将来」
その時であるとも思えません。
そもそも実行環境を提示しない状態において、この手の質疑を進める事が問題なのかもしれ
ませんが、初心者が環境提示の必要性を判断し得るくらいなら、初めから「この」質問なんて
してはこないだろうとも思うのですよねw 難しいところではあります。
バクシ
会議室デビュー日: 2004/10/06
投稿数: 12
投稿日時: 2004-11-25 09:46
kitoさん,ご忠告ありがとうございます。

世の中には,現実にServletAPI 2.2しか使えないサーバもあります。けっして,「大昔」ではなく,「現状」なのです。

httpヘッダを参照すれば「デタラメな文字列が生成されないようなコーディング」が可能になりますか?



[ メッセージ編集済み 編集者: バクシ 編集日時 2004-11-25 09:50 ]
MINE
会議室デビュー日: 2003/07/02
投稿数: 17
投稿日時: 2004-11-25 16:32
横から失礼します。
ちょっと気になったので一言。

一昔前は、どのようにしても正しいコードで2バイト文字を取得
できなかったため、プログラマが自前で正しいコードに変換するしか
なかったために、String#getBytes()を利用していたはずです。
現在はいちいち自前で変換しなくてもAPIやサーバの環境設定などで、
文字コードを指定できるようになってきています。手段が存在するのであれば、
素直に正しいコードで受け取るほうが正しいのではないでしょうか。

個人的には、手段があるのに、いちいち自前で変換するのは動作上問題なくても
やっぱり変な気がします。
また、ServletAPI 2.2でもアプリケーション毎にデフォルト文字エンコーディングを
設定できるサーバもありますし、一定時期以降のサーバは大体そうなっているのでは
ないでしょうか?

kitoさんのいうとおり、String#getBytesは他に手段がない環境での最終手段だと思います。
また、「おまじない」という言葉はやっている内容に対して何を意味しているのかを
考えず、思考停止的にコードを埋め込ませることにつながる危険がないでしょうか。
環境設定やAPIなどで、正しい文字列を取得できるようになっている環境で、
思考停止的にString#getBytesを埋め込んだ場合、逆に文字化けを引き起してしまうことに
つながると思いますし、「おまじない」でString#getBytesというのは
現状にそぐわないように思います

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