- PR -

Runtime#exec実行時の文字コード

投稿者投稿内容
yattu
会議室デビュー日: 2005/08/05
投稿数: 7
投稿日時: 2006-07-24 10:48
Linux(EUC_JP環境)、JDK142_05上で、Runtime#execでシェルスクリプト(Cシェルスクリプトとして作成)を実行すると、String配列でシェルスクリプトに渡したパラメータに関して文字化けが発生します。

状況としては、全角チルダ「〜」(\uff5e)や、マイナス「−」(\uff0d)、ダッシュ「―」(\u2015)などが、「!)」に文字化けしています。
 →シェルスクリプトから、他ファイルにリダイレクトして確認した

Unicode→EUC_JPの変換に失敗しているように思えるのですが、そもそもRuntime#execのAPIに文字コード変換に関するものもなく、回避策があるのかどうかも分かりません。

また、Windows上でテストをしてみたところ、特に化けることはなかったため、Unicode→Shift_JISへの変換は特に問題がないようです。

当件に関して何か回避策お持ちの方いらっしゃいましたら、ご教示願います。

[ メッセージ編集済み 編集者: yattu 編集日時 2006-07-24 10:51 ]
ひろ@ya
大ベテラン
会議室デビュー日: 2006/02/23
投稿数: 168
投稿日時: 2006-07-24 16:30
パラメータを一度ファイルに書き出しておいてスクリプトにはファイル名だけを渡す様にできませんか?(同時実行に対する考慮は必要ですが)
小僧
ぬし
会議室デビュー日: 2002/08/14
投稿数: 526
投稿日時: 2006-07-24 17:16
実行したいシェルスクリプトに渡したいパラメータを付けた状態の
シェルスクリプトファイルをJava側で生成して、それをexecで実行
するという案はいかがでしょうか。
※Cシェルに不慣れなのでbshで書きます

パラメータを渡して実行したいシェルスクリプト: foo.sh
Javaからコマンドラインで渡したいパラメータ: 今日は〜悪い天気−
Javaで作成するシェルスクリプト: javafoo.sh

◆内容
コード:

#!/bin/sh

#環境変数などの設定

foo.sh 今日は〜悪い天気−




これをJavaで生成してEUCコードで保存してから、

Runtime#execで
コード:

sh javafoo.sh


なんていう感じで。

ひろさんの懸念する同時実行への配慮などは、生成するファイルの
ファイル名をユニークにするとかで対応できそうな気がします。
文字列をコマンドラインで渡すということは、シェルとして特殊な扱いになる
文字をエスケープしないと危ないですね。


[ メッセージ編集済み 編集者: 小僧 編集日時 2006-07-24 17:18 ]
coasm
大ベテラン
会議室デビュー日: 2001/11/26
投稿数: 237
投稿日時: 2006-07-24 23:55
引用:

状況としては、全角チルダ「〜」(\uff5e)や、マイナス「−」(\uff0d)、ダッシュ「―」(\u2015)などが、「!)」に文字化けしています。



そもそも、ユニコードffe5とかff0dという文字をEUCコードに変換することはできません。
なぜなら、それらの文字に対応するEUCの文字が存在しないからです。

http://www.atmarkit.co.jp/fjava/rensai3/mojibake02/mojibake02.html

yattu
会議室デビュー日: 2005/08/05
投稿数: 7
投稿日時: 2006-07-25 10:51
ひろさん、小僧さん、coasmさん、ご回答ありがとうございます。

ひろさん、小僧さんにご教示頂いた、動的にスクリプトを作成
する、というアプローチは、システム用件上実現が難しいのです・・。

やはりどうしてもjava内で解決する必要があり、
全角チルダ「〜」(\uff5e),マイナス「−」(\uff0d)に関しては、
coasmさんにご教示頂いたサイトを元に、下記のような関数を作り、
問題回避ができました。

private static String toJIS(String s) {
StringBuffer sb = new StringBuffer();
char c;
for (int i = 0; i < s.length(); i++) {
c = s.charAt(i);
switch (c) {
case 0x2225:
c = 0x2016;
break;
case 0xff0d:
c = 0x2212;
break;
case 0xffe0:
c = 0x00a2;
break;
case 0xffe1:
c = 0x00a3;
break;
case 0xffe2:
c = 0x00ac;
break;
case 0xff5e:
c = 0x301c;
break;
}
sb.append(c);
}
return new String(sb);
}

ダッシュ「―」(\u2015)に関しては、
http://www.atmarkit.co.jp/fjava/rensai3/mojibake02/mojibake02.html
の対象からは外れそうですが、化けています。
これに関しても、なんらかの既知の問題が存在するのでしょうか?
小僧
ぬし
会議室デビュー日: 2002/08/14
投稿数: 526
投稿日時: 2006-07-25 11:10
Unicode→EUC_JP
で化けてしまうのであれば、
Unicode→JIS→EUC_JP (※またはEUC_JP_LINUX)
で変換するというのはどうでしょうか。
厳密に試す時間が無いので、JIS→EUC_JP_LINUXをAntのcopyタスクで試してみました。
コード:
<target name="cp">
    <copy encoding="JIS" outputencoding="EUC_JP_LINUX"
    file="from.txt"
    tofile="to.txt"/>
</target>



〜も―(ダッシュ)も化けずに日本語EUCに変換できたみたいです。
昔、メールの処理で試したことがあったものでやってみました。
いかがでしょうか。
coasm
大ベテラン
会議室デビュー日: 2001/11/26
投稿数: 237
投稿日時: 2006-07-25 13:07
ダッシュ「―」(\u2015)が化けるのも同じ理由です。
0x2015 → 0x2014 と変換すればよかったはず。

# 参照先の記事にある表は、「すべてを網羅」していません。
yattu
会議室デビュー日: 2005/08/05
投稿数: 7
投稿日時: 2006-07-25 15:03
小僧さん
ありがとうございます。

ちなみに、
>Unicode→JIS→EUC_JP (※またはEUC_JP_LINUX)
>で変換するというのはどうでしょうか。
というのは、

//オリジナル文字列
String orgStr=・・・
//JISとしてのユニコード
String jisUni = new String(orgStr.getBytes("JIS"),"JIS");
//EUCとしてのユニコード
String eucjpUni = new String(jisUni.getBytes("EUC_JP"),"EUC_JP");
//eucjpUniをRuntime#execに渡す
・・・

というようなことを指されていますか?
(ちなみに上記の通りのコードだと、化けています)


coasmさん
ご教示ありがとうございます。
ご指摘頂いたマッピングで、ダッシュに関しても変換できました。
※世の中に「すべてを網羅」した表があればよいのですが・・



[ メッセージ編集済み 編集者: yattu 編集日時 2006-07-25 15:12 ]

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