- PR -

文字コード変換について(Tomcat/PostgreSQL)

投稿者投稿内容
未記入
ベテラン
会議室デビュー日: 2005/04/16
投稿数: 51
投稿日時: 2005-04-16 23:20
■ 質問の概要

Tomcatアプリケーションで
画面(Webブラウザ)から
PostgreSQL内のDBへ
データ登録・更新を行おうとすると
文字化けします。
どうすれば解決できるか教えてください。


■開発(実行)環境

1) OS
Windows2000 5.00.2195 Service Pack 4

2) J2SDK
1.4.1_05

3) TOMCAT
5.0.16

4) Eclipse
2.1.2

5) Eclipse TOMCAT PLUGIN
com.sysdeo.eclipse.tomcat_2.2.1

6) DB = PostgreSQL
8.0

7) pstgres JDBC driver
pg74.215.jdbc3.jar

Webブラウザ = Internet Explorer
6.0 SP1


■事象

EclipseやTomcatを使用して
Javaのアプリケーションから
PostgreSQLで構築したDBへの
JDBC接続をテストしています。

1 まずJavaアプリケーションのテストを行いました。

 1-1 Selectからコンソールへの表示(標準出力)
Statement.executeQueryによってSelect文を実行、
resultSet.getString("[カラム名]");
によってデータを取得し
そのままSystem.out.printで表示させます。

-> 問題なく表示できました。(Eclipseコンソール上)

-> このとき、
System.out.println ( new String ( name.getBytes("EUC_JP"), "iso-2022-jp")
と記入すると逆に上手く動きませんでした。

 1-2 プログラムからのInsertやUpdate
statement.executeUpdate("INSERT INTO address VALUES ( ・・・
を実行してDBへ値を登録したり値の更新をしたりします。

-> 問題なく表示できました。
  ※ 文字コード変換はしていません。

2 次にTomcatアプリケーションのテストを行いました。

 2-1 SelectからWebブラウザへの表示
Statement.executeQueryによってSelect文を実行、
resultSet.getString("[カラム名]");
によってデータを取得し
そのままPrintWriter.printlnにて表示させます。

-> 問題なく表示できました。
  ※ 文字コード変換はしていません。

 2-2 【問題発生】WebブラウザからDBデータ値のInsertやUpdate
prepareStatementを用いて
setStringで各カラムに値を設定後、
登録や更新を実行します。

-> 文字変換を無視して実行すると文字化けします。
例: xに文字列を格納し
(prepareStatement.setString(1, x);
  
  psqlを用いてDBの値をSelectすると
    WARNING: ignoring unconvertible UTF-8 character・・・
  といったワーニングが出力されます。
  DBデータ値をTomcatアプリケーションから参照したときも
  当然、文字化けしています。

-> そこで 文字変換を実行すると
上手く動きません。

prepareStatement.setString ( 1, new String ( x.getBytes ("8859_1"), "EUC_JP"));
と書いて実行しましたが、
Insert、Updateは行われず
画面は真っ白です。
(URLはこのInsertメソッドで止まっています。
本来はexecuteUpdate()の後別の画面を表示するメソッドが呼び出されます。)

その他ためしに"MS932"や"Shift_JIS"等々
色々試しましたが結果は同じでした。
つばさ
ベテラン
会議室デビュー日: 2005/02/05
投稿数: 54
投稿日時: 2005-04-17 13:24
つばさです。

ブラウザから取得したパラメータが正しくデコードできていますでしょうか?
以下のようにサーブレットで実行して問題なく登録できます。
req.setCharacterEncoding("Windows-31J");
String key = (String)req.getParameter("key");
String sql = "insert into temp_key (dkey) values(?)" PreparedStatement ps = conn.prepareStatement(sql);
ps.setString(1, key);
int rc = ps.executeUpdate();

PostgresのデータベースのエンコーディングはEUC_JP
JDBCのドライバはPostgres8.0Win版に付属のpostgresql-8.0.309.jdbc2ee.jar
で試してみました。
参考まで。
未記入
ベテラン
会議室デビュー日: 2005/04/16
投稿数: 51
投稿日時: 2005-04-18 08:56
レスありがとうございました。

問題の切り分けができました。
そもそもDBMS以前にブラウザより取得したパラメータのデコードができていませんでした。

そこで教わったとおりsetCharacterEncodingを利用したのですが
引数として「Windows-31J」はじめ様々な値を設定したものの
どれにしてもやはり文字化けしてしまい困っています。

よろしければアドバイスをお願いいたします。
山本 裕介
ぬし
会議室デビュー日: 2003/05/22
投稿数: 2415
お住まい・勤務地: 恵比寿
投稿日時: 2005-04-18 10:05
html のエンコーディングと setCharacterEncoding を合わせましょう。
また、全ての文字が化けるのか、"〜"など特定の文字がばけるのか、などの情報も入れると話が早いかもしれません。
未記入
ベテラン
会議室デビュー日: 2005/04/16
投稿数: 51
投稿日時: 2005-04-18 13:20
アドバイスをありがとうございます。

このメソッドの前に、まずDB内のデータをブラウザに一覧表示させています。
そのときのエンコードは「日本語(EUC)」です。

(一覧表示メソッド内で
response.setContentType("text/html; charset=EUC_JP");
と指定。)


それに合わせてInsertを行うメソッドでも
request.setCharacterEncoding("EUC_JP");
としましたが、
getParameterにて取得した各値をSystem.outしてみると
日本語が文字化けています。
次のように「?」が比較的多く現れます。
(Eclipseコンソールより)

NAME = ??¶¶
Address = μ???

そのため、DB内にInsertは行われますが
さらに文字化けた状態で登録され
NAME = 〓¶¶
Address = 〓〓〓
といった調子になっています。

(半角数字文字列はSystem.out時点では文字化けてはいませんが、
DBに登録された時点でNullになっています。
まずブラウザから入力された値のデコード問題解決が先決だと思っていますが、
DBMSとの文字コード変換についてもその後の課題になるかと思っています。)

何かよきアドバイスがございましたら宜しくお願いいたします。
uk
ぬし
会議室デビュー日: 2003/05/20
投稿数: 1155
お住まい・勤務地: 東京都
投稿日時: 2005-04-18 13:56
引用:

未記入さんの書き込み (2005-04-18 13:20) より:
このメソッドの前に、まずDB内のデータをブラウザに一覧表示させています。
そのときのエンコードは「日本語(EUC)」です。
(一覧表示メソッド内で
response.setContentType("text/html; charset=EUC_JP");
と指定。)


本当にEUCで表示されているか、ブラウザのエンコードを確認してください。

引用:

それに合わせてInsertを行うメソッドでも
request.setCharacterEncoding("EUC_JP");
としましたが、
getParameterにて取得した各値をSystem.outしてみると
日本語が文字化けています。


このメソッドはどのタイミングで実行しているでしょうか。この前に他のパラメータを取得
していたり、あるいはサーブレットフィルタを使用していたりしませんか?
未記入
ベテラン
会議室デビュー日: 2005/04/16
投稿数: 51
投稿日時: 2005-04-18 14:30
レスをありがとうございます。

1) ブラウザの「エンコード」を確認しましたが 確かに「日本語(EUC)」となっています。

2) PGMの実行順序は次のようになっています。

 ア. DB内データの一覧表示画面(Servlet)表示。
     ※ response.setContentType("text/html; charset=EUC_JP");

   -> その中に「登録」という文字列を持つ
     <a href=・・・>タグがあり、そこで指定されているURLには
     「?」マークと共にパラメータが設定されています。
     ここに設定されている値は実行するメソッドを表すための文字列です。

 イ. リクエスト文字列によって処理を振り分けるメソッドが
   URLに含まれた文字列をキャッチし、指定されたメソッドを呼び出します。

 ウ. 指定されたメソッドが実行されます。(新規登録用画面表示メソッド)
   このメソッドはFormを持ち、
   画面にいくつかのテキストボックスを表示します。
     ※ response.setContentType("text/html; charset=EUC_JP");

   値が入力されsubmitボタンが押下されると
   action属性で指定されたURLへジャンプします。
   -> ここでも「?」マークと共に次に実行すべきメソッド名を保持しています。

 エ. リクエスト文字列によって処理を振り分けるメソッドが
   URLに含まれた文字列をキャッチし、指定されたメソッドを呼び出します。
   ここで呼び出されるのが Insert メソッドです。

 オ. Insertメソッドに処理が移ります。
   このメソッドが実際に画面から入力された値を受け取り
   DBへの登録処理を行います。
     ※ request.setCharacterEncoding("EUC_JP");
       と指定していますが、
       (String)request.getParameter("x");
     で取得した値をSystem.outしてみると
       前記のとおり文字化けしています。

※ なお、サーブレットフィルタは使用していません。

何卒宜しくお願い申し上げます。
uk
ぬし
会議室デビュー日: 2003/05/20
投稿数: 1155
お住まい・勤務地: 東京都
投稿日時: 2005-04-18 19:04
引用:

未記入さんの書き込み (2005-04-18 14:30) より:
レスをありがとうございます。
 エ. リクエスト文字列によって処理を振り分けるメソッドが
   URLに含まれた文字列をキャッチし、指定されたメソッドを呼び出します。
   ここで呼び出されるのが Insert メソッドです。

 オ. Insertメソッドに処理が移ります。
   このメソッドが実際に画面から入力された値を受け取り
   DBへの登録処理を行います。
     ※ request.setCharacterEncoding("EUC_JP");
       と指定していますが、
       (String)request.getParameter("x");
     で取得した値をSystem.outしてみると
       前記のとおり文字化けしています。


「エ.」で参照しているのはクエリ文字列だけですか? パラメータ取得をおこなってはいませんか?
もしそこでパラメータの取得をしているのであれば、この前にrequest.setCharacterEncoding
を実行しなければなりません。もしこの部分を変更できないのであれば、サーブレットフィルタ
なり配置記述子の設定なりでリクエストのエンコーディングを設定してやる必要があります。

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