- PR -

DB問合せのservletで文字化け

1
投稿者投稿内容
kic
会議室デビュー日: 2004/11/01
投稿数: 9
投稿日時: 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内ですでに文字化けがおきています。
kic
会議室デビュー日: 2004/11/01
投稿数: 9
投稿日時: 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 ]
kito
ベテラン
会議室デビュー日: 2003/03/24
投稿数: 59
お住まい・勤務地: Osaka
投稿日時: 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行程度で動作するコードを書きましょう。
・どこまでできていて、どこから出来ていないのか、ひとつずつ確認しましょう。
kic
会議室デビュー日: 2004/11/01
投稿数: 9
投稿日時: 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 ]
uk
ぬし
会議室デビュー日: 2003/05/20
投稿数: 1155
お住まい・勤務地: 東京都
投稿日時: 2004-11-04 15:04
引用:

kicさんの書き込み (2004-11-04 14:45) より:
また、String#getBytes()を使わないで
エラーが出力されないようにする方法があればお聞かせ願えないでしょうか。


SearchItemServlet#doPostの最初で
request.setCharacterEncoding("Windows-31J");
を実行する。

kic
会議室デビュー日: 2004/11/01
投稿数: 9
投稿日時: 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 ]
uk
ぬし
会議室デビュー日: 2003/05/20
投稿数: 1155
お住まい・勤務地: 東京都
投稿日時: 2004-11-04 16:46
引用:

kicさんの書き込み (2004-11-04 16:07) より:
ukさん、レスありがとうございます。
SearchItemServletは検索処理ですが
検索処理はうまく動いているので
RegisterItemServletのことでしょうか。


その通りです。コピペをミスりました。

引用:

RegisterItemServlet#doPostの最初で
request.setCharacterEncoding("Windows-31J");
を実行したんですがシステムエラーになりました。


「システムエラー」ってなんですか? エラーが出たのであれば、もう少し詳しく書いてください。

引用:

Windows-31J以外にEUCJIS等試してみても
システムエラーに入ってしまいます。


意味を理解せずに闇雲に試してもダメですよ。


[ メッセージ編集済み 編集者: uk 編集日時 2004-11-04 16:47 ]
kic
会議室デビュー日: 2004/11/01
投稿数: 9
投稿日時: 2004-11-04 17:47
ukさん、レスありがとうございます。

>「システムエラー」ってなんですか? エラーが出たのであれば、もう少し詳しく書いてください。

どうやらクラスファイルをFTPでバイナリーでアップしてなかったようです。


RegisterItemServlet#doPostの最初で
request.setCharacterEncoding("EUCJIS");

としたら無事文字化けせずに表示されました!!

(DBはEUC-JPにinitしてあるのでEUCJIS設定)

長い間悩んでいたのでとても嬉しいです!
ありがとうございました!!
1

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