- PR -

データベースから取得したShift-JISをEUCに変換したい

投稿者投稿内容
tnakamura
会議室デビュー日: 2004/03/25
投稿数: 5
投稿日時: 2004-03-25 22:31
はじめまして、初めて投稿させていただきます。


サーバ solaris
データベース SymfoWARE
JSPの contentType="text/html; charset=Euc-JP"

JSP → Bean で処理を行い処理結果をJSPで表示させています。
それでBean内でテーブルを読み、必要な項目を取得しているのですが、
その取得する項目の中に"Shift-JIS"の日本語文字を格納している項目があります。

ResultSet.getString(columnIndex) で"Shift-JIS"の日本語文字を取得すると
文字化けをしてしまいます。

また

new String(s.getBytes("SJIS"),"EUC-JP") でやっても文字化けしてしまいます。

第1引数、第2引数をいろいろ変えてやってみたのですが文字化けでした。

ちなみにテーブルに格納されている日本語文字が"EUC-JP"の場合は
ResultSet.getString(columnIndex) で文字化けせずに取得することができました。

getBytes 以外の方法で InputStreamReader を使って"Shift-JIS"の日本語文字を
取得しようとしたのですがこちらも文字化けをしてしまいました。
(いくつか引数を変えてやってみましたがダメでした)

下記にロジックを書いておきます。

どなたか良い方法をご存知でしたら教えて頂きたいと思っております。
よろしくお願いします。

--------------------------------------------------------------------------
@

while (lrs.next()){
  Cht = new Hashtable();
  lrowCount++;
  // 列情報の取得
  for ( int i = 0 ; i < lcolumnCount ; i++ ){
    String sGet = new String();

    if(i == 3){
       String sKanji = lrs.getString(i+1);
//文字化け  sGet = new String(sKanji.getBytes("8859_1"),"JISAutoDetect");
//文字化け  sGet = new String(sKanji.getBytes("8859_1"),"EUC-JP");
//文字化け  sGet = new String(sKanji.getBytes("EUC-JP"),"EUC-JP");
//文字化け  sGet = new String(sKanji.getBytes("SJIS"),"SJIS");
//文字化け  sGet = new String(sKanji.getBytes("8859_1"),"SJIS");
       sGet = new String(sKanji.getBytes("SJIS"),"EUC-JP");

    }else {
       sGet = lrs.getString(i+1);
    }
    sGet = cTool.NVL( sGet, "");
    Cht.put(String.valueOf(i), sGet);
  }
  vRet.addElement(Cht);
}

--------------------------------------------------------------------------
A

while (lrs.next()){
  Cht = new Hashtable();
  lrowCount++;
  // 列情報の取得
  for ( int i = 0 ; i < lcolumnCount ; i++ ){
    String sGet = new String();
    if(i == 3){

//文字化け  InputStreamReader isr = new InputStreamReader(lrs.getAsciiStream(i+1));
//文字化け  InputStreamReader isr = new InputStreamReader(lrs.getAsciiStream(i+1),"EUC-JP");
         InputStreamReader isr = new InputStreamReader(lrs.getAsciiStream(i+1),"SJIS");
         BufferedReader br = new BufferedReader(isr);
         StringWriter sw = new StringWriter();
         try {
           int c;
           while((c = br.read()) != -1){
             sw.write(c);
           }
           br.close();
         } catch (IOException e){
           ci.printTrace("■■■ 失敗:");
         }
         sGet = new String(sw.toString().getBytes("SJIS"),"EUC-JP");

    }else {
       sGet = lrs.getString(i+1);
    }
    sGet = cTool.NVL( sGet, "");
    Cht.put(String.valueOf(i), sGet);
  }
  vRet.addElement(Cht);
}

--------------------------------------------------------------------------

永井和彦
ぬし
会議室デビュー日: 2002/07/03
投稿数: 276
お住まい・勤務地: 東京都
投稿日時: 2004-03-26 12:13
永井です。

最初にお断りしておきます。この投稿は直球回答では無いです。

「MACから入れたデータはMACからしか参照しない。機種依存文字も全部使いたい」と同時に「Windowsから(以下略)」……というような特殊な要件で無い限りは、DBに入れる段階でDB内の文字列は全てDBの文字エンコーディングとして指定されているものに変換されているべきです。

つまり「DBの文字コード設定は何になっていたかなー」は必要ですが、「この文字列の文字エンコードが何だったかなー」は考えないで済む状況になっているべきだということです。

と言うか、こうなっていないと、一般的なDBアクセスツール(Ex. SQL-Plus)で内容参照したと
きに化け化け(より正確には、データによって化けたり化けなかったりが混在)で見られない状況になってしまいます。また、内容を扱う際にも非常に面倒な手続きが必要になります。
#「この行を見るときはこの設定で接続、別の行を見るときはこっちの設定で」とかになります

というわけで、根っこの思考方針を見直すことをお勧めします。

---

さて、本題にいきます。まず、状況情報が足りません。

1. DB自体の文字コード設定は何ですか?Java-DBの接続設定では文字コード設定はどのようになされていますか?
2. DBアクセスツールで内容参照したとき、対象文字列は化けずに表示されますか?
3. 「化ける」というのは、具体的に「何が」「どのように」化けますか?コピペしましょう。
4. 「EUC_JPの文字列」や「Shift_JIS(アンダースコアでお願いします)の文字列」は、どのようにしてDB内に入れられたのでしょうか?

本来的には、文字化け系(DB連動)の質問はこの辺が分からないと何とも言えません。
#4はちょっと特殊な例なので、普通は無いですが……

で、解決方法としてお勧めなのは「DBに入れる段階で文字コードを揃えておく」です。今のままのデータを根性で表示する方法(コード)も一応考えたのですが、未来が無いのでここには書きません。


[ メッセージ編集済み 編集者: 永井和彦 編集日時 2004-03-26 12:46 ]
Cluster
ぬし
会議室デビュー日: 2003/03/06
投稿数: 289
お住まい・勤務地: 大阪
投稿日時: 2004-03-26 12:33
ソースは細かく読んでないですが・・・

# 根本的には、永井和彦さんのご指摘の通りとは思いますが、
# どうしても現状のままでいく場合のヒントとして・・・

JavaのString型は、内部的には全てutf-8で保持しています。
(Unicodeでしたっけ?フォロー乞う(爆))

なので、resultsetからgetStringした時点では、既に化けていると思われます。
resultsetから同じカラムをgetByteしてみて、確認されてはどうでしょうか?

#推測ですが、JDBCドライバが、DBから値を取得した時点で、勝手にEUCであると
#解釈して、SJISの文字列に対してEUC→UTF-8の変換を掛けてるのではないかと・・・
#(SJISの文字列ならば、本来はSJIS→UTF-8の変換を掛けてString型にするべき)
#SymfoWARE というDBMSはよく知らないので本当にあてずっぽうですし、
#どこ(DBの設定?JDBCドライバのパラメータ?)を直せばいいのかは
#分かりませんが。

ちなみに、

引用:

tnakamuraさんの書き込み (2004-03-25 22:31) より:
new String(s.getBytes("SJIS"),"EUC-JP") でやっても文字化けしてしまいます。



は、全く無意味です。このコードは、
「UTF-8の文字列をSJISに変換し、そのバイト列を取り、そのバイト列をEUC-JPと解釈して文字列化する」ということです。元の文字列の文字コードに関わらず、化けて当然ですよね

taku
ぬし
会議室デビュー日: 2002/11/12
投稿数: 918
お住まい・勤務地: 墨田区→中野区
投稿日時: 2004-03-26 13:11
引用:

Clusterさんの書き込み (2004-03-26 12:33) より:
JavaのString型は、内部的には全てutf-8で保持しています。
(Unicodeでしたっけ?フォロー乞う(爆))


 そうです、Unicodeです。
Cluster
ぬし
会議室デビュー日: 2003/03/06
投稿数: 289
お住まい・勤務地: 大阪
投稿日時: 2004-03-26 13:36
引用:

takuさんの書き込み (2004-03-26 13:11) より:

 そうです、Unicodeです。



takuさん、フォローありがとうございます。

それにしても、やっぱり間違ってたか(爆)
論旨は間違ってないと思うんですけどね。
tnakamura
会議室デビュー日: 2004/03/25
投稿数: 5
投稿日時: 2004-03-26 14:59
永井和彦さん、Clusterさん、有難うございます。

状況情報が足らず、すみませんでした。

1については
ECUだと思うのですが・・・・

2については
Tera Term ProでTerminal SetupのKanji(receive)をSJISにしてから
SQLでselect文を実行して確認してみたところ文字化けしませんでした。

3については
"部門1001        "(部門1001+全角スペース8個)
 が
"??????????????"(?が14個)に化けています。

4については
私のほうにはバイナリデータを頂いてそれをSymfoWAREのRDBコマンドで
DBにインサートしました。
実際にはプログラムよりDBにインサートしています。


プログラムのほうの修正ができないみたいなので今のままのデータから
表示させたいのですが何か良い方法がありましたら教えてもらえませんか。
よろしくお願いします。


あとClusterさんより指摘のありましたgetByteからデータを取ってくるのは、
まだやっていなかったので早速試してみます。
有難うございます。
永井和彦
ぬし
会議室デビュー日: 2002/07/03
投稿数: 276
お住まい・勤務地: 東京都
投稿日時: 2004-03-26 15:32
永井です。

大体の事情は了解した(つもり)です。

DBにデータを流し込む部分に関してはもう完成して手を入れられない。内容を閲覧するようなJSPを作りたい……ということですね。
一応確認なのですが、今入っている(要件として、表示対象になっている)データとしては「Shift_JISの文字列」と仰っているものだけで、「EUC-JPの文字列」に関してはtnakamuraさんが色々と試行錯誤なさった際に使われたダミーデータ(要件外)ですよね?

引用:

JSPの contentType="text/html; charset=Euc-JP"



パターン1:「contentType="text/html; charset=Shift_JIS"」に変えて、普通に#getStringしただけでは出ないでしょうか?

パターン2: BeanからDBに接続している部分があると思うのですが、その際の接続文字列に「charset=EUC_JP」のような部分はないでしょうか?あったら"EUC-JP"を"Shift_JIS"変更してみて下さい。そして普通に#getString。ContextTypeはEUC-JPでもShift_JISでも構いません

パターン3: ContextTypeも接続部分も現状のままで
コード:

String sKanji = lrs.getString(i+1);
sGet = new String(sKanji.getBytes("EUC-JP"),"Shift_JIS");



……全滅の予感(^^;;

[ メッセージ編集済み 編集者: 永井和彦 編集日時 2004-03-26 15:34 ]
しょむ
ぬし
会議室デビュー日: 2001/09/06
投稿数: 430
投稿日時: 2004-03-26 17:47
基本的な知識の確認。

DBに正常に文字が格納されている(DB用クライアントで文字化けしない(?))、
DBの言語設定とJDBCドライバの接続の言語設定がしっかりしているならば、特に文字コード変換を意識しなくても、

[DB]<-(?)->[JDBC Driver]<-(UCS-2)->[Java]

という内部コードになり、特に変換しなくても文字化けしないはずです。
まぁJDBCドライバがちゃんと国際化を意識していることが前提ですが。

# 余談ですが、出力に関しても、contentType を指定すれば自動的に UCS-2->XX してくれます

DBへの流し込みが特殊っぽいですから、まずは新規にSJISで空のDBとテーブルを作り、
Javaからの日本語入出力を試してみてください。
それでうまくいくなら接続設定は合っているはず。
うまくいかなければ接続設定のみなおし。

テスト用DBでうまくいくのに本番ではうまくいかなければDBの作り方やデータの流し込み方法の再考。それでもうまくいかなければ、バイナリデータとして取り出して自前で処理。

JDBCドライバが腐っている場合は…どう腐っているのかによりますね…

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