デフォルトのJava文字エンコードの設定


362

JVM(1.5.x)で使用されるデフォルトの文字エンコーディングをプログラムで適切に設定するにはどうすればよいですか?

-Dfile.encoding=whatever古いJVM を使用する方法であった方法を読んだことがあります。私が入らない理由のために、私はその贅沢はありません。

私が試してみました:

System.setProperty("file.encoding", "UTF-8");

そして、プロパティは設定されますが、getBytes以下の最後の呼び出しでUTF8を使用するようには見えません:

System.setProperty("file.encoding", "UTF-8");

byte inbytes[] = new byte[1024];

FileInputStream fis = new FileInputStream("response.txt");
fis.read(inbytes);
FileOutputStream fos = new FileOutputStream("response-2.txt");
String in = new String(inbytes, "UTF8");
fos.write(in.getBytes());

優秀なコメントの人たち-そして私がすでに自分で考えていたこと。残念ながら、基盤となるString.getBytes()呼び出しがあり、私が制御することはできません。私が現在それを回避するために見る唯一の方法は、デフォルトのエンコーディングをプログラムで設定することです。他の提案はありますか?

6
関連のない質問かもしれませんが、UTF8が「UTF8」、「UTF-8」、または「utf8」で設定されている場合は違いがありますか。最近、IBM WAS 6.1のEJBおよびWEBコンテナーが、エンコードの定義に使用される(大文字と小文字を区別する)文字列の扱いが異なることに気付きました。
igor.beslic

5
詳細ですが、UTF-8よりもUTF-8を優先してください(前者のみが標準です)。これは2012年にも適用されます...
クリストフ・ルシー

4
file.encodingプロパティの設定または読み取りはサポートされていません
McDowell

@ericksonクエリではまだ明確ではありませんが、文字ベースのI / Oストリームが使用されている場合(class Reader&のすべてのサブクラスclass Writer)に「file.encoding」が関連しているというのは本当ですか?のでclass FileInputStreamI / Oストリームベースのバイトで、なぜ1はバイトベースのI / Oストリームに文字セットを気にする必要がありますか?
14

回答:


311

残念ながら、file.encodingJVMの起動時にプロパティを指定する必要があります。時間によって、あなたの主な方法は、使用する文字エンコーディング入力されているString.getBytes()と、デフォルトのコンストラクタをInputStreamReaderし、OutputStreamWriter永続的にキャッシュされています。

エドワード・グレックは指摘し、このような特殊な場合には、環境変数がJAVA_TOOL_OPTIONS でき、このプロパティを指定するために使用されていますが、通常はこのように行われています:

java -Dfile.encoding=UTF-8  com.x.Main

Charset.defaultCharset()file.encodingプロパティへの変更を反映しますが、デフォルトの文字エンコーディングを決定する必要があるコアJavaライブラリのコードのほとんどは、このメカニズムを使用しません。

エンコードまたはデコードする場合、file.encodingプロパティを照会するかCharset.defaultCharset()、現在のデフォルトのエンコードを検索し、適切なメソッドまたはコンストラクターオーバーロードを使用してそれを指定できます。


9
完全を期すために、少し工夫すれば、Gary Croninのおかげで、実際に使用されているデフォルトのエンコーディング(キャッシュされているとおり)にアクセスできることを付け加えておきます。byte [] byteArray = {'a'}; InputStream inputStream = new ByteArrayInputStream(byteArray); InputStreamReaderリーダー=新しいInputStreamReader(inputStream); String defaultEncoding = reader.getEncoding(); lists.xcf.berkeley.edu/lists/advanced-java/1999-October/...
Stijnデウィット

2
JDK-4163515にfile.encoding、JVM起動後のsyspropの設定に関するいくつかの情報があります。
Caspar 2014

2
コマンドがWindows、Linux、およびMacで完全に機能しなかった原因を頭に
かいていたので、

Java Spring Bootの場合は私の答えを確認してください:stackoverflow.com/a/48952844/986160
Michail Michailidis

170

JVM™ツールインタフェースドキュメント...

たとえば、埋め込みVMや単にスクリプト内の深いVMでコマンドラインにアクセスしたり変更したりできるとは限らないJAVA_TOOL_OPTIONSため、これらの場合にエージェントを起動できるように変数が用意されています。

(Windows)環境変数JAVA_TOOL_OPTIONS-Dfile.encoding=UTF8System設定すると、JVMが起動するたびに(Java)プロパティが自動的に設定されます。次のメッセージがに投稿されるため、パラメータが取得されたことがわかりますSystem.err

Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF8


"Picked up ..."ステートメントがTomcatログに出力されることを知っていますか?
thatidiotguy 2012

1
こんにちは、エドワード・グレッチ。解決策をありがとう。別のフォーラム投稿で私の問題が解決されました。stackoverflow.com/questions/14814230/...
スマウグ

8
UTF8またはUTF-8
小さな

1
@Tiny Javaは両方を理解します。stackoverflow.com/questions/6031877/...
DLightに

あなたの解決策は私の時間を節約しました、ありがとうございました!!
ソブハン

67

私は間違いなく機能するハッキーな方法を持っています!!

System.setProperty("file.encoding","UTF-8");
Field charset = Charset.class.getDeclaredField("defaultCharset");
charset.setAccessible(true);
charset.set(null,null);

このようにして、charsetが設定されていないと思われるJVMをだまし、実行時にUTF-8に再度設定するようにします!


2
NoSuchFieldException for me
SparK 2013年

10
ハッキングが機能するためには、セキュリティマネージャがオフになっていると想定する必要があります。JVMフラグを設定する方法がない場合は、(おそらく)セキュリティマネージャが有効になっているシステムもあるでしょう。
ヨナタン2013

3
JDK9はこのハッキングを承認しなくなりましたWARNING: An illegal reflective access operation has occurred • WARNING: Illegal reflective access by [..] • WARNING: Please consider reporting this to the maintainers of [..] • WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations • WARNING: All illegal access operations will be denied in a future release
dotwin 2018年

1
@Enerccio:それは良い答えではありません、それは汚いハックであり、問​​題が発生するのを待っています。これは緊急時の対策としてのみ使用してください。
sleske 2018年

1
@Enerccio:Javaがこれを設定する方法を「すべき」かどうかは議論の余地があります。開発者が関連する場合はいつでも、エンコーディングを明示的に指定すべきであると主張することもできます。とにかく、このソリューションは長期的に深刻な問題を引き起こす可能性があるため、「緊急時のみ」の注意事項です。実際、緊急の使用でさえ問題があります。サポートされている方法あるため、別の回答で説明されているようにJAVA_TOOL_OPTIONSを設定します。
sleske 2018年

38

プラットフォームのデフォルトの文字セットを設定するよりも良いアプローチだと思います。特に、アプリケーションのデプロイメントへの影響に制限があるようで、プラットフォームは言うまでもなく、より安全なを呼び出すことString.getBytes("charsetName")です。このようにして、アプリケーションは制御できないものに依存しません。

私は個人的にはString.getBytes()非推奨にすべきだと思っています。これは、開発者がデフォルトの文字セットの変更を考慮に入れていないという、多くのケースで深刻な問題を引き起こしたためです。


18

元の質問にはお答えできませんが、アドバイスをさせていただきます。JVMのデフォルトのエンコーディングに依存しないでください。コードでは、常に希望するエンコーディング(つまり "UTF-8")を明示的に指定するのが最善です。そうすれば、異なるシステムやJVM構成でも動作することがわかります。


7
もちろん、デスクトップアプリを作成し、エンコードメタデータを含まないユーザー指定のテキストを処理する場合を除いて、ユーザーが何を使用しているかについては、プラットフォームのデフォルトのエンコードが最適です。
Michael Borgwardt

@MichaelBorgwardt「プラットフォームのデフォルトのエンコーディングが最も適切だと思われる場合」デフォルトを変更したいというのはあまり良い考えではないことをアドバイスしているようです。つまり、可能な限り明示的なエンコーディングを使用し、他に何も可能でない場合は提供されたデフォルトを使用しますか?
Raedwald

1
@Raedwald:はい、それは私が意味したことです。プラットフォームのデフォルトのエンコーディングは、(少なくともエンドユーザーのマシンでは)システムが設定されているロケールのユーザーが通常使用しているものです。これは、より良い(つまり、ドキュメント固有の)情報がない場合に使用する必要がある情報です。
Michael Borgwardt、2012

1
@MichaelBorgwardtナンセンス。ライブラリを使用して入力エンコーディングを自動検出し、BOMを使用してUnicodeとして保存します。それがエンコーディング地獄に対処して戦う唯一の方法です。
Aleksandr Dubinsky

お二人は同じページにいないと思います。Michaelがデコードについて話し、Raedwaldがデコード後の処理について話します。
WesternGun、2016年

12

これを試して :

    new OutputStreamWriter( new FileOutputStream("Your_file_fullpath" ),Charset.forName("UTF8"))

5

私たちは同じ問題を抱えていました。この記事(およびその他の記事)からのいくつかの提案を計画的に試みたが、役に立たなかった。また、-Dfile.encoding=UTF8を追加してみましたが、何も機能していないようです。

この問題を抱えている人々のために、以下の記事は最終的に私たちは、ロケール設定は破ることができる方法を説明し追跡助けunicode/UTF-8でのJava/Tomcat

http://www.jvmhost.com/articles/locale-breaks-unicode-utf-8-java-tomcat

~/.bashrcファイルでロケールを正しく設定することでうまくいきました。


4

私は多くのことを試しましたが、ここのサンプルコードは完璧に動作します。 リンク

コードの要点は次のとおりです。

String s = "एक गाव में एक किसान";
String out = new String(s.getBytes("UTF-8"), "ISO-8859-1");

4

Spring Bootを使用しfile.encodingていて、JVMで引数を渡したい場合は、次のように実行する必要があります。

mvn spring-boot:run -Drun.jvmArguments="-Dfile.encoding=UTF-8"

これはJTwig、テンプレートを使用しており、オペレーティングシステムにはANSI_X3.4-1968System.out.println(System.getProperty("file.encoding"));

これが誰かを助けることを願っています!


2

私はAmazon(AWS)Elastic Beanstalkを使用していますが、UTF-8に正常に変更しました。

Elastic Beanstalkで、[設定]> [ソフトウェア]の[環境プロパティ]に移動します。(名前)JAVA_TOOL_OPTIONSを(値)-Dfile.encoding = UTF8で追加します

保存後、環境はUTF-8エンコーディングで再起動します。


1

あなたが何をしているのかはっきりしないので、現時点では制御できません。宛先ファイルに別のOutputStreamクラスを挿入できる場合は、定義した文字セット(デフォルトではUTF-8)の下で文字列をバイトに変換するOutputStreamのサブタイプを使用できます。変更されたUTF-8で十分な場合は、次を使用できますDataOutputStream.writeUTF(String)

byte inbytes[] = new byte[1024];
FileInputStream fis = new FileInputStream("response.txt");
fis.read(inbytes);
String in = new String(inbytes, "UTF8");
DataOutputStream out = new DataOutputStream(new FileOutputStream("response-2.txt"));
out.writeUTF(in); // no getBytes() here

このアプローチが現実的でない場合は、データフローと実行環境の観点から制御できることと制御できないことをここで正確に明確にすると役立つ場合があります(ただし、決定よりも簡単に言うことができる場合もあります)。幸運を。


5
DataInputStreamとDataOutputStreamは、プレーンテキストファイルで使用してはならない特別な目的のクラスです。彼らが採用する修正UTF-8は、実際のUTF-8と互換性がありません。さらに、OPがソリューションを使用できる場合、彼はこのジョブに適切なツール、OutputStreamWriterも使用できます。
アランムーア

1
mvn clean install -Dfile.encoding=UTF-8 -Dmaven.repo.local=/path-to-m2

コマンドはexec-maven-pluginと連携して、jenkinsタスクの構成中に発生する次のエラーを解決しました。

Java HotSpot(TM) 64-Bit Server VM warning: ignoring option MaxPermSize=512m; support was removed in 8.0
Error occurred during initialization of VM
java.nio.charset.IllegalCharsetNameException: "UTF-8"
    at java.nio.charset.Charset.checkName(Charset.java:315)
    at java.nio.charset.Charset.lookup2(Charset.java:484)
    at java.nio.charset.Charset.lookup(Charset.java:464)
    at java.nio.charset.Charset.defaultCharset(Charset.java:609)
    at sun.nio.cs.StreamEncoder.forOutputStreamWriter(StreamEncoder.java:56)
    at java.io.OutputStreamWriter.<init>(OutputStreamWriter.java:111)
    at java.io.PrintStream.<init>(PrintStream.java:104)
    at java.io.PrintStream.<init>(PrintStream.java:151)
    at java.lang.System.newPrintStream(System.java:1148)
    at java.lang.System.initializeSystemClass(System.java:1192)

0

2つのシステムプロパティを一緒に設定すると、システムはすべてをutf8に取り込みます

file.encoding=UTF8
client.encoding.overrideUTF-8

7
client.encoding.overrideプロパティはWebSphere固有のようです。
Christophe Roussy 2012


0

最近、私は地元の会社のLotus Notes 6.5システムにぶつかり、Zhongwen以外のローカライズされたWindowsインストールでWebメールが識別できない文字を表示することがわかりました。数週間オンラインで掘り下げて、ほんの数分前にそれを理解しました:

Javaプロパティで、次の文字列をランタイムパラメータに追加します。

-Dfile.encoding=MS950 -Duser.language=zh -Duser.country=TW -Dsun.jnu.encoding=MS950

この場合、UTF-8設定は機能しません。


0

私のチームは、Windowsを搭載したマシンで同じ問題に遭遇しました。次に、2つの方法でそれを解決することができました。

a)環境変数を設定します(Windowsシステム設定でも)

JAVA_TOOL_OPTIONS
-Dfile.encoding = UTF8

b)次のスニペットをpom.xmlに導入します。

 -Dfile.encoding=UTF-8 

以内に

 <jvmArguments>
 -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8001
 -Dfile.encoding=UTF-8
 </jvmArguments>
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.