web-dev-qa-db-ja.com

デフォルトのエンコーディングへの依存、私は何を使用する必要があり、なぜですか?

FindBugsはバグを報告します:

デフォルトのエンコーディングへの依存バイトからストリング(またはストリングからバイト)への変換を実行し、デフォルトのプラットフォームエンコーディングが適切であると想定するメソッドの呼び出しが見つかりました。これにより、プラットフォーム間でアプリケーションの動作が異なります。代替APIを使用して、文字セット名または文字セットオブジェクトを明示的に指定します。

FileReaderを次のように使用しました(コードの一部):

public ArrayList<String> getValuesFromFile(File file){
    String line;
    StringTokenizer token;
    ArrayList<String> list = null;
    BufferedReader br = null;
    try {
        br = new BufferedReader(new FileReader(file));
        list = new ArrayList<String>();
        while ((line = br.readLine())!=null){
            token = new StringTokenizer(line);
            token.nextToken();
            list.add(token.nextToken());
    ...

バグを修正するには、変更する必要があります

br = new BufferedReader(new FileReader(file));

br = new BufferedReader(new InputStreamReader(new FileInputStream(file), Charset.defaultCharset()));

そして、PrintWriterを使用すると、同じエラーが発生しました。だから今、私は質問があります。 FileReaderとPrintWriterを使用できる(する必要がある)場合、それが適切でない場合は、デフォルトのエンコーディングに依存しますか? 2番目の質問は、Charset.defaultCharset()を適切に使用することです。このメソッドを使用して、ユーザーのOSの文字セットを自動的に定義することにしました。

21
Nikolas

ファイルがアプリケーションの制御下にあり、ファイルをプラットフォームのデフォルトエンコーディングでエンコードする場合、デフォルトのプラットフォームエンコーディングを使用できます。これを明示的に指定することで、あなたと将来のメンテナにとって、これがあなたの意図であることを明確にします。これは、たとえば、テキストエディターの合理的なデフォルトになり、このプラットフォーム上の他のエディターが読み取れるファイルを書き込みます。

一方、可能な文字をファイルに書き込むことができるようにする場合は、UTF8などのユニバーサルエンコーディングを使用する必要があります。

また、ファイルが外部アプリケーションからのものである場合、または外部アプリケーションと互換性があると想定される場合は、この外部アプリケーションが期待するエンコーディングを使用する必要があります。

あなたが理解しなければならないのは、あなたがマシンでやっているようにファイルを書き、同じデフォルトエンコーディングを持たない別のマシンでやっているようにそれを読むと、必ずしもできるとは限らないということですあなたが書いたものを読んでください。 UTF8などの特定のエンコーディングを使用して書き込みおよび読み取りを行うと、ファイルの書き込み時に使用されるプラットフォームにかかわらず、ファイルは常に同じになります。

23
JB Nizet

理想的には、次のとおりです。

try (InputStream in = new FileInputStream(file);
     Reader reader = new InputStreamReader(in, StandardCharsets.UTF_8);
     BufferedReader br = new BufferedReader(reader)) {

...または:

try (BufferedReader br = Files.newBufferedReader(path, StandardCharsets.UTF_8)) {

...ファイルがUTF-8としてエンコードされていると仮定します。

Unicode変換フォーマットではないほとんどすべてのエンコーディングは、自然言語データでは使用されなくなりました。 Unicodeなしではサポートできない言語があります。

20
McDowell

アプリケーションの外部にあり、ユーザーが作成したテキストファイルなど、ユーザーのローカルエンコーディングであると想定されるファイルを読み取る場合は、常にデフォルトのエンコーディングを使用する必要があります。ユーザーが後でそのファイルをどのように使用するかに応じて、このようなファイルを書き込むときにデフォルトのエンコーディングを使用することができます。

not他のファイル、特にアプリケーション関連のファイルにはデフォルトのエンコーディングを使用する必要があります。

たとえば、アプリケーションが構成ファイルをテキスト形式で書き込む場合は、常にエンコーディングを指定する必要があります。一般的に、UTF-8はほとんどすべてと互換性があるため、常に適切な選択です。そうしないと、他の国のユーザーが突然クラッシュする可能性があります。

これは、文字エンコーディングだけでなく、日付/時刻、数値、またはその他の言語固有の形式にも限定されます。たとえば、米国のマシンでデフォルトのエンコーディングとデフォルトの日付/時刻文字列を使用し、ドイツのサーバーでそのファイルを読み取ろうとすると、半分が意味不明で、残りの半分が月/日が混乱またはオフになっていることに驚くかもしれません夏時間のために1時間ずつ。

3
TwoThe

PrintWriterを使用している場合、

File file = new File(file_path);
Writer w = new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_16.name());
PrintWriter pw = new PrintWriter(w);
pw.println(content_to_write);
pw.close();
0
prime