- PR -

ファイルI/Oの文字コードについて

投稿者投稿内容
みーちく
大ベテラン
会議室デビュー日: 2002/08/29
投稿数: 131
投稿日時: 2002-12-25 18:44
こんにちわ。みーちくと申します。

件名の件について、自分では解決できないので、皆様のお知恵をお借りしたいと思います。
宜しくお願い致します。

JAVA:jsdk1.4.1
DB:PostgreSQL7.2.1

コード:
public boolean test_read(String url, String[] name){
  String ss = "";
  BufferedReader fin;
  /* オブジェクトの作成 */
  Kikan_DB db = new Kikan_DB();
  /* 今日の日付を取得 */
  Date date       = new Date();
  DateFormat df   = new SimpleDateFormat("[yyyy年MM月dd日HH時mm分ss秒]");
  String today    = df.format(date);

  try{
    for(int i=0; i<name.length; i++){
      fin = new BufferedReader(new InputStreamReader(new FileInputStream(url + name[i]), "JISAutoDetect"));
      System.out.println(today + "\t読込み開始:" + name[i]);
      write_rireki(today + "\t読込み開始:"+ name[i]);
      while ((ss = fin.readLine()) != null) {
        StringTokenizer st     = new StringTokenizer(ss, ",");
        String client_cd       = st.nextToken();
        String dept_cd         = st.nextToken();
        String client_name     = st.nextToken();
        String client_a_name   = st.nextToken();
        db.test_add(client_cd,dept_cd,client_name,client_a_name);
      }
      System.out.println(today + "\t読込み終了:" + name[i]);
      write_rireki(today + "\t読込み終了:"+ name[i]);
      fin.close();
    }
  return true;
  } catch(Exception e) {
    System.out.println("Error: " + e);
    write_error("読込みでエラーが発生しました。\n" + e);
    System.exit(1);
    return false;
  }
}




上記のようなコードがあります。
特定のディレクトリから、CSVファイルを持ってきて、カンマ区切りを1行ずつ処理をして、DBに書き込むというプログラムを作成しました。
入力ファイルは「SJIS」か「EUC_JP」かわからない状態なので、「JISAutoDetect」を使用しております。このままDBに登録すると、一部文字化けしてしまいます。
そこで、読み込んで変数にセットするところで、エンコーディングを変更したのですが、うまく動作できませんでした。

コード:
     【変更部分】
      while ((ss = fin.readLine()) != null) {
        StringTokenizer st     = new StringTokenizer(ss, ",");
        String client_cd       = UnicodeString(st.nextToken());
        String dept_cd         = UnicodeString(st.nextToken());
        String client_name     = UnicodeString(st.nextToken());
        String client_a_name   = UnicodeString(st.nextToken());
        db.test_add(client_cd,dept_cd,client_name,client_a_name);
      }

private String UnicodeString(String s) throws UnsupportedEncodingException {
  return new String(s.getBytes("UTF-8"), "EUC-JP");
}



このような場合はどのようにすれば良いのでしょうか。
DBでは「??????????」のように登録されました。
宜しくお願い致します。
ayum
常連さん
会議室デビュー日: 2002/03/28
投稿数: 44
お住まい・勤務地: 東京
投稿日時: 2002-12-25 19:00
エンコーディングを変更しているUnicodeString(String)というメソッド、
内部で引数で渡ってきた文字列をまずUTF-8と仮定してgetByteしてますよね。
でも入力ファイルはSJISかEUC_JPで入ってくるとの事ですので、
それを無理やりUTF-8としてgetByteしてEUC_JPに変えようとしても確実に化けます。
????という化け方は私の周りでは俗に「UTF化け」と呼ばれているものですが(余談)。
文字コード変換を行うなら

new String(s.getBytes("JISAutoDetect"), "UTF-8")

の方が自然かなと。
とはいえ、これでは一部文字化けという問題はおそらく解決しないでしょう・・・。
インプットファイルの中に機種依存文字とかは入っていますか?
あるいは、ファイルから切り出した文字列は、
DBに入れる前にダンプしてみても化けますか?
それともDBに入れて取り出した際に化けますか?
みーちく
大ベテラン
会議室デビュー日: 2002/08/29
投稿数: 131
投稿日時: 2002-12-25 19:19
ayumさん

早速の返信ありがとうございます。

引用:

内部で引数で渡ってきた文字列をまずUTF-8と仮定してgetByteしてますよね。
でも入力ファイルはSJISかEUC_JPで入ってくるとの事ですので、
それを無理やりUTF-8としてgetByteしてEUC_JPに変えようとしても確実に化けます。



「InputStreamReader」は指定の文字コードをUnicodeへ変換して入力するものだと思っていたのですが。。。。
StringTokenizerでカンマ区切りを変数に入れた場合、文字コードは「Unicode」になっているのかなと思ってました。

>new String(s.getBytes("JISAutoDetect"), "UTF-8")
早速試してみたのですが、下記のようなエラーとなりました。
Error: java.io.UnsupportedEncodingException: JISAutoDetect

>インプットファイルの中に機種依存文字とかは入っていますか?
>あるいは、ファイルから切り出した文字列は、
>DBに入れる前にダンプしてみても化けますか?
>それともDBに入れて取り出した際に化けますか?

こちらについては、早速調べてみます。
宜しくお願い致します。
tabby
ベテラン
会議室デビュー日: 2002/06/26
投稿数: 55
お住まい・勤務地: 埼玉県・東京都
投稿日時: 2002-12-25 19:58
JISAutoDetectを使う時って、こういう書き方しませんでしたっけ?

new String(s.getBytes("8859_1"), "JISAutoDetect");

sの文字列を8859_1のエンコーディングに従ったバイト配列に変換して、
それをJISAutoDetectのエンコーディングで内部表現?にする。
#内部表現=デフォルトのエンコード
しょむ
ぬし
会議室デビュー日: 2001/09/06
投稿数: 430
投稿日時: 2002-12-25 20:33
new BufferedReader(new InputSteramReader(new FileInputStream(もげ), "JISAutoDetect")))

の時点で、readLine で読まれてくる String は「ファイルを "JISAutoDetect" で解析し、Java 的 String (= UCS2(UTF16?)) に直したもの 」というマットウな形式になってますから、ナニもする必要はないです。そのまま DB につっこめば OK。
DB の文字コードがどうのなんてことはドライバが解決してくれます。

そこで失敗してるかどうかは、読み込んだ String を System.out.println でもすればいいでしょう。失敗してるなら JISAutoDetect の失敗なので、使えない、ってことで。

ただし、SJIS (=Shift_JIS) と CP932 (=Windows-31J=MS932)の違いには注意。
JISAutoDetect は「シフトJIS」を「SJIS」で扱いますので、機種依存文字は使えません。
みーちく
大ベテラン
会議室デビュー日: 2002/08/29
投稿数: 131
投稿日時: 2002-12-26 10:37
tabbyさん、しょむさん

返信ありがとうございました。

JISAutoDetect → SJISに変更し、読み込んだStringをSystem.out.printlnしてみました。読み込んだ時点で文字化けしてました。
機種依存文字という事で解決いたしました。
皆様ありがとうございました。

ちょっと余談なのですが。
今後の勉強の為にも教えていただけないでしょうか。
JAVAで文字のエンコードを調べるクラスとかはあるのでしょうか?

宜しくお願い致します。
asip
ベテラン
会議室デビュー日: 2001/12/27
投稿数: 77
投稿日時: 2002-12-31 11:56
み〜ちくさんへ
 JISAutoDetect → SJIS ではなく JISAutoDetect → Windows-31J(=MS932)にすれば
 機種依存文字も扱えるはずです。
 しょむさんの書かれたのを補足すると、JISAutoDetectはJIS、SJIS、EUC_JPを
 自動判別するためのものであり、Wundows-31J=MS932(WindowsのシフトJIS独自拡張)
 はその判別対象ではありません。また、SJISとWundows-31Jの自動判別はおそらく
 できません。
  また、PostgreSQL7.2.Xで機種依存文字を文字化けなしに扱うためにはPostgreSQL
 にバッチをあてる必要があります。PostgreSQL7.3.Xはデフォルトでほとんどの機種
 依存文字を文字化けなしに扱えます。

#Windows31-JではなくWindows-31Jでした。

[ メッセージ編集済み 編集者: asip 編集日時 2003-01-06 20:52 ]
みーちく
大ベテラン
会議室デビュー日: 2002/08/29
投稿数: 131
投稿日時: 2003-01-06 11:56
asipさん

返信ありがとうございました。

引用:

JISAutoDetect → SJIS ではなく JISAutoDetect → Windows31-J(=MS932)にすれば機種依存文字も扱えるはずです。


早速試してみたいと思います。
引用:

PostgreSQL7.2.Xで機種依存文字を文字化けなしに扱うためにはPostgreSQLにバッチをあてる必要があります。


いろいろと探してみたのですが、バッチが見当たりませんでした。
大変申し訳ないのですが、どこにあるのか教えていただけませんでしょうか?

宜しくお願い致します。

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