- - PR -
DB問合せのservletで文字化け
1
投稿者 | 投稿内容 | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2004-11-01 17:13
今、DB問合せのservletで文字化けが起こっており自力で解決策が見出せないので、
ご意見お願いします 環境は、 DBサーバー Redhat9、PostgreSQL7.3.3(文字コードEUC_JP)、 j2sdk-1_4_0、Tomcat4.1.18、Apache2.0.44(文字コードEUC_JPに指定) Webサーバー(動作試し環境) WinXP、j2sdk1.4.0_03、Tomcat4.1.18 JAVA開発環境 eclipse2.1.0(エンコードms932) においてキーワードからDB登録アイテム検索のservletを作りました。 しかし登録時のDB内ですでに文字化けがおきています。 文字コードに注目しておっていくと・・・ @クライアント(登録画面 register.html) Shift_JISで入力 AServlet、Beans(登録処理 RegisterItemServlet.java,RegisterItemBean.java) Unicodeに変換 ・・・Java の文字列は java.lang.String オブジェクトで Unicode になっている ■文字コードに関係するJAVAソース抜粋■ RegisterItemBean.java ------------------------------------------------------------------------- //SQL 文を UNICODE から EUC に変換 String eucSql = new String( insertSQL.getBytes( "EUCJIS" ), "8859_1" ); ------------------------------------------------------------------------------- 参考:http://www2.licorp.co.jp/pugly/postgres/jwjdbc.html BPostgreSQL(登録処理 psql) EUC_JPで書き込み psql -l List of databases Name | Owner | Encoding -----------+----------+---------- eiboard | postgres | EUC_JP AにおけるSQL 文を UNICODE から EUC に変換する処理を加える以前には A→BのDB登録時以下のエラーが起きていました WARNING: UtfToLocal: could not convert UTF-8 (0xc281). Ignored しかし、処理を加えてエラーはなくなり、 ロジック上はSQL 文を UNICODE から EUC に変換しPostgreSQLでEUC_JPで書き込み 可能 なはずなんですが、未だに登録時のDB内ですでに文字化けがおきています。 | ||||||||||||
|
投稿日時: 2004-11-02 13:57
自己レスです
DBに手入力で登録した画面も検索画面で文字化けしていることから html,servlet,beans,DB,jsp間でエンコーディングがごちゃごちゃになってるのかも しれません 詳しくソースを書いてみます このプログラムの全体としての流れは登録画面でDB登録したものを、 検索画面で検索条件をもとにDB検索して クライアント画面に表示するといった単純なものです。 まず登録は。。。 @クライアント(登録画面 register.html) 手入力で情報を入力し、DB登録時に割り当てられるIDを プライマリーキーItemIDとします。 AServlet、Beans(登録処理 RegisterItemServlet.java,RegisterItemBean.java) ■文字コードに関係するソース抜粋■ 登録画面で入力された内容をSQL文でINSERTします。 RegisterItemBean.java -------------------------------------------------------------------------- //Insert用SQL文 insertSQL = "Insert Into Item " + "values (?,?,?,?,?,?,?,?,?)"; //SQL 文を UNICODE から EUC に変換 String eucSql = new String( insertSQL.getBytes( "EUCJIS" ), "8859_1" ); ; //コネクション取得クラスをインスタンス化 ConnectDB condb = new ConnectDB(); //DBから新しいコネクションを取得 con = condb.getDBConnection(); //SQL分をPrepareStatementにセット PreparedStatement pst = con.prepareStatement(eucSql); eir = "パラメータセット前"; pst.setString(2,new String( title.getBytes( "EUCJIS" ), "8859_1" )); eir = "パラメータセット2"; pst.setString(3,new String(summary.getBytes( "EUCJIS" ), "8859_1")); eir = "パラメータセット3"; pst.setString(4,new String(detail.getBytes( "EUCJIS" ), "8859_1" )); Date.valueOf("2004-3-5"); eir = today; eir = "パラメータセット4"; pst.setString(5,new String(today.getBytes( "EUCJIS" ), "8859_1" )); eir = "パラメータセット5"; pst.setString(6,new String(limitdate.getBytes( "EUCJIS" ), "8859_1" )); eir = "パラメータセット6"; pst.setString(7,new String(name.getBytes( "EUCJIS" ), "8859_1" )); eir = "パラメータセット7"; pst.setString(8,new String(contact.getBytes( "EUCJIS" ), "8859_1" )); eir = "パラメータセット8"; pst.setString(9,new String(infotype.getBytes( "EUCJIS" ), "8859_1" )); eir = "パラメータセット9"; //新しいアイテムIDを取得 itemId = getNextID(); //パラメータをセット pst.setString(1,itemId); eir = "パラメータセット1"; //Insert実行 reflectedCnt = pst.executeUpdate(); //コミット con.commit(); ------------------------------------------------------------------------------- 参考:http://www2.licorp.co.jp/pugly/postgres/jwjdbc.html RegisterItemServlet.java -------------------------------------------------------------------------- public void doPost(HttpServletRequest request, HttpServletResponse response) { try { // エラー発生時、エラーJSPの出力にも失敗した時用PrintWriter取得 response.setContentType("text/html; charset=SJIS"); out = response.getWriter(); //登録情報を、HTTPオブジェクトから取得 String title = request.getParameter("title"); String summary = request.getParameter("summary"); String detail = request.getParameter("detail"); String today = request.getParameter("today"); String limitdate = request.getParameter("limitdate"); String name = request.getParameter("name"); String contact = request.getParameter("contact"); String infotype = request.getParameter("infotype"); //登録Beanをインスタンス化 RegisterItemBean rb = new RegisterItemBean(); //登録Beanを呼び出す。 //割り当てられたItemIDを取得 String assignedItemId = rb.registerItem(title,summary,detail,today,limitdate, name,contact,infotype); //割り当てられたItemIDをセット request.setAttribute("assignedItemId",assignedItemId); //JSPを呼び出す。 RequestDispatcher rDispatcher = request.getRequestDispatcher(jspSetPath + "/register_end.jsp"); rDispatcher.forward(request,response); -------------------------------------------------------------------------- BPostgreSQL(登録処理 psql) EUC_JPで書き込み psql -l List of databases Name | Owner | Encoding -----------+----------+---------- eiboard | postgres | EUC_JP ■テーブルの中身抜粋■ id | title | summary | detai l | registerdate | limitdate | ownername | ownercontact | infotype ----------+-----------------------+-------------------------------+------------- ---------+--------------+------------------+-----------+--------------+--------- 16 | ?y???束 | ?i?`?u?` | ?譬?? | 2004/10/29 | ?? | ???? | ?????? | 1 18 | タイトル | サマリ | 出ティる | 2004/05/01 | 0 | オーナー | aaaaa@aaaa | 1 17 | タイトル | サマリ | 出ティる | 2004/05/01 | 0 | オーナー | aaaaa@aaaa | 1 19 | ? | ? | ?? | 2004/11/2 | ??? | ??? | ???? | 1 (ID17,18はSQL手入力でDB登録なので非文字化け) 検索は。。。 @クライアント(検索画面 search.html) AServlet、Beans(検索処理 SearchItemServlet.java,SearchItemBean.java) ■文字コードに関係するソース抜粋■ 検索画面での条件にあったものをSQL文でサーチします。 SearchItemBean.java -------------------------------------------------------------------------- searchSQL = "select ID,Title,Summary,RegisterDate,LimitDate," + "OwnerName,OwnerContact,infotype " + "from Item "; //条件部を付加 searchSQL = searchSQL + editConditionSection(itemID,infoType,keyWord); //SQL 文を UNICODE から EUC に変換 String eucSql_s = new String( searchSQL.getBytes( "EUCJIS" ), "8859_1" ); //SQL分をPrepareStatementにセット PreparedStatement pst = con.prepareStatement(searchSQL); //各パラメータをセット int pi = 0; //ItemIDの設定がある場合 if (itemID.length()!=0) { pst.setString(1,itemID); } //ItemIDの設定がない場合 else { if (!infoType.equals("0")) { pi++; pst.setString(pi,new String(infoType.getBytes( "EUCJIS" ), "8859_1" )); } if (keyWord.length()!=0) { pi++; pst.setString(pi,new String(keyWord.getBytes( "EUCJIS" ), "8859_1" )); pi++; pst.setString(pi,new String(keyWord.getBytes( "EUCJIS" ), "8859_1" )); pi++; pst.setString(pi,new String(keyWord.getBytes( "EUCJIS" ), "8859_1" )); } } ResultSet resultset = pst.executeQuery(); while(resultset.next()) { ItemSummaryBean summary = new ItemSummaryBean(); //IDを取得 summary.setId(new String(resultset.getBytes(1),"JISAutoDetect" )); //タイトルを取得 summary.setTitle(new String(resultset.getBytes(2),"JISAutoDetect" )); //概要を取得 summary.setSummary(new String(resultset.getBytes(3),"JISAutoDetect" )); //登録日を取得 summary.setRegisterDate(new String(resultset.getBytes(4),"JISAutoDetect" )); //有効日を取得 summary.setLimitDate(new String(resultset.getBytes(5),"JISAutoDetect" )); //登録者を取得 summary.setOwnerName(new String(resultset.getBytes(6),"JISAutoDetect" )); //登録者連絡先を取得 summary.setOwnerContact(new String(resultset.getBytes(7),"JISAutoDetect" )); //情報種別を取得 summary.setInfoType(new String(resultset.getBytes(8),"JISAutoDetect" )); //1レコード分をArrayListに格納 al.add(summary); } //コネクション終了 con.close(); con = null; SearchItemServlet.java -------------------------------------------------------------------------- public void doPost(HttpServletRequest request, HttpServletResponse response) { //検索結果格納用ArrayList ArrayList resultArrayList; try { // エラー発生時、エラーJSPの出力にも失敗した時用PrintWriter取得 response.setContentType("text/html; charset=SJIS"); out = response.getWriter(); //out.println("<html><title>検索エラー</title></html>"); //検索条件を、HTTPオブジェクトから取得 String itemID = request.getParameter("itemID"); if(itemID==null){ itemID=""; } String keyWord = request.getParameter("keyword"); if(keyWord==null){ keyWord=""; } String infoType = request.getParameter("infotype"); if(infoType==null){ infoType="0"; } String searchType = request.getParameter("searchtype"); //検索用Beanをインスタンス化 SearchItemBean sb = new SearchItemBean(); //概要検索 if (searchType.equals("0")) { //検索実行 resultArrayList = sb.searchItemSammary(itemID,infoType,keyWord); //HTTPリクエストオブジェクトに、検索結果をセット request.setAttribute("summaryResult",resultArrayList); //JSPを呼び出す。 RequestDispatcher rDispatcher = request.getRequestDispatcher(jspSetPath+ "/result.jsp"); rDispatcher.forward(request,response); } -------------------------------------------------------------------------- B検索結果画面 result.jsp -------------------------------------------------------------------------- <%@ page contentType="text/html; charset=MS932" %> <%@ page import="javax.servlet.*,java.util.*" %> <jsp:useBean id="summary" scope="session" class="beans.ItemSummaryBean" /> <% // パラメータの取得&アイテムリストの検索 ArrayList summarylist = new ArrayList(); summarylist = (ArrayList)request.getAttribute("summaryResult"); %> (略) <% for(int i = 0; i < summarylist.size(); i++){ summary = (beans.ItemSummaryBean)summarylist.get(i); %> <tr> <td> <% String s1 = summary.getRegisterDate(); out.println(s1); %> </td> <td> <% String s2 = summary.getTitle(); out.println(s2); %> ・ ・ (略) -------------------------------------------------------------------------- 実際にIEで表示される画面 2004/10/29 ?y???ツ。テア 1 ?i?`?u?` ?? ???? ?????? 2004/05/01 繧ソ繧、繝医Ν 1 繧オ繝槭Μ 0 繧ェ繝シ繝翫? aaaaa@aaaa 2004/05/01 繧ソ繧、繝医Ν 1 繧オ繝槭Μ 0 繧ェ繝シ繝翫? aaaaa@aaaa 2004/11/2 ? 1 ? ??? ??? ???? ・半角英数字は化けずに表示される ・真ん中のふたつがDB直接入力 ・ひらがなは全部?で漢字などは?y???ツ。テアのように化ける 。。。。このなかで誤ったコーディングをしている箇所などありましたら ご指摘いただけたら幸いです _________________ [ メッセージ編集済み 編集者: kic 編集日時 2004-11-02 14:00 ] | ||||||||||||
|
投稿日時: 2004-11-03 02:48
>。。。。このなかで誤ったコーディングをしている箇所などありましたら
>ご指摘いただけたら幸いです ということなので、文字コードについて間違っているところを挙げてみます。 >//SQL 文を UNICODE から EUC に変換 >String eucSql = new String( insertSQL.getBytes( "EUCJIS" ), "8859_1" ); >pst.setString(2,new String( title.getBytes( "EUCJIS" ), "8859_1" )); >pst.setString(3,new String(summary.getBytes( "EUCJIS" ), "8859_1")); >pst.setString(4,new String(detail.getBytes( "EUCJIS" ), "8859_1" )); >pst.setString(4,new String(detail.getBytes( "EUCJIS" ), "8859_1" )); >pst.setString(6,new String(limitdate.getBytes( "EUCJIS" ), "8859_1" )); >pst.setString(7,new String(name.getBytes( "EUCJIS" ), "8859_1" )); >pst.setString(8,new String(contact.getBytes( "EUCJIS" ), "8859_1" )); >pst.setString(9,new String(infotype.getBytes( "EUCJIS" ), "8859_1" )); >String eucSql_s = new String( searchSQL.getBytes( "EUCJIS" ), "8859_1" ); >//SQL 文を UNICODE から EUC に変換 >String eucSql_s = new String( searchSQL.getBytes( "EUCJIS" ), "8859_1" ); >pst.setString(pi,new String(infoType.getBytes( "EUCJIS" ), "8859_1" )); >pst.setString(pi,new String(keyWord.getBytes( "EUCJIS" ), "8859_1" )); >pst.setString(pi,new String(keyWord.getBytes( "EUCJIS" ), "8859_1" )); >pst.setString(pi,new String(keyWord.getBytes( "EUCJIS" ), "8859_1" )); >summary.setId(new String(resultset.getBytes(1),"JISAutoDetect" )); >summary.setTitle(new String(resultset.getBytes(2),"JISAutoDetect" )); >summary.setSummary(new String(resultset.getBytes(3),"JISAutoDetect" )); >summary.setRegisterDate(new String(resultset.getBytes(4),"JISAutoDetect" )); >summary.setLimitDate(new String(resultset.getBytes(5),"JISAutoDetect" )); >summary.setOwnerName(new String(resultset.getBytes(6),"JISAutoDetect" )); >summary.setOwnerContact(new String(resultset.getBytes(7),"JISAutoDetect" )); >summary.setInfoType(new String(resultset.getBytes(8),"JISAutoDetect" )); 文字コードに関して誤ったコーディングをしているところは以上で全部です。 String#getBytes()を使うのを止めましょう。 >参考:http://www2.licorp.co.jp/pugly/postgres/jwjdbc.html 情報が古すぎます。参考にしてはいけません。 最後に、 ・丸投げはやめましょう。 ・質問するときは、丸投げでも抜粋でもなく、5-10行程度で動作するコードを書きましょう。 ・どこまでできていて、どこから出来ていないのか、ひとつずつ確認しましょう。 | ||||||||||||
|
投稿日時: 2004-11-04 14:45
kitoさん、レスありがとうございます。
getBytesの処理ははじめは使っていなかったのですが 一番はじめに書いてあるように WARNING: UtfToLocal: could not convert UTF-8 (0xc281). Ignored のエラーがでるので使うようにしたんです。 それでその後気づいたんですがeclipseのソースエンコードがms932で コンパイルエンコードがutf-8になっていたことが問題だったみたいです。 String#getBytes()を使うのを止め、コンパイルエンコード指定をしないようにしたら検索処理はうまくいきました。 (DBに手入力でインサートした文字化けしてない情報はちゃんと表示されるようになりました) 参考:http://www.atmarkit.co.jp/fjava/rensai2/webopt08/webopt08.html ですがDB登録処理時に WARNING: UtfToLocal: could not convert UTF-8 (0xc2a2). Ignored とテラターム上にエラーがでるようになってしまいました。 コンパイルエンコードをSJIS,EUCJP,ms932・・・ 登録処理ソース String eucSql = new String( insertSQL.getBytes( "EUCJIS" ), "8859_1" ); のgetBytesの中身を String eucSql = new String( insertSQL.getBytes( "UTF-8" ), "EUCJIS" ); ・ ・ などいろいろ変えて試したのですがうまくいきません。 (WARNING: UtfToLocal: could not convert UTF-8 (0xefbfbd). Ignored のエラーがでます) String#getBytes()を使うのを止めてもエラーがでるので やはりString#getBytes()を使ってエンコード処理する必要があると思うのですが 何故String#getBytes()は使ってはいけないのでしょうか。 また、String#getBytes()を使わないで エラーが出力されないようにする方法があればお聞かせ願えないでしょうか。 [ メッセージ編集済み 編集者: kic 編集日時 2004-11-04 14:48 ] [ メッセージ編集済み 編集者: kic 編集日時 2004-11-04 14:56 ] | ||||||||||||
|
投稿日時: 2004-11-04 15:04
SearchItemServlet#doPostの最初で request.setCharacterEncoding("Windows-31J"); を実行する。 | ||||||||||||
|
投稿日時: 2004-11-04 16:07
ukさん、レスありがとうございます。
SearchItemServletは検索処理ですが 検索処理はうまく動いているので RegisterItemServletのことでしょうか。 (ちなみにSearchItemServlet#doPostの最初で request.setCharacterEncoding("Windows-31J"); を実行してもだめでした) RegisterItemServlet#doPostの最初で request.setCharacterEncoding("Windows-31J"); を実行したんですがシステムエラーになりました。 Windows-31J以外にEUCJIS等試してみても システムエラーに入ってしまいます。 やはりRegisterItemBeanのSQLのDB登録処理のところが 問題ではないかと思います。 ここの辺りに詳しい方いらっしゃいましたら お知恵をかしていただけないでしょうか。 [ メッセージ編集済み 編集者: kic 編集日時 2004-11-04 16:11 ] | ||||||||||||
|
投稿日時: 2004-11-04 16:46
その通りです。コピペをミスりました。
「システムエラー」ってなんですか? エラーが出たのであれば、もう少し詳しく書いてください。
意味を理解せずに闇雲に試してもダメですよ。 [ メッセージ編集済み 編集者: uk 編集日時 2004-11-04 16:47 ] | ||||||||||||
|
投稿日時: 2004-11-04 17:47
ukさん、レスありがとうございます。
>「システムエラー」ってなんですか? エラーが出たのであれば、もう少し詳しく書いてください。 どうやらクラスファイルをFTPでバイナリーでアップしてなかったようです。 RegisterItemServlet#doPostの最初で request.setCharacterEncoding("EUCJIS"); としたら無事文字化けせずに表示されました!! (DBはEUC-JPにinitしてあるのでEUCJIS設定) 長い間悩んでいたのでとても嬉しいです! ありがとうございました!! |
1