19

java.lang.StringCodingから:

String csn = (charsetName == null) ? "ISO-8859-1" : charsetName;

これはJava.lang.getBytes()から使用されるものです。Linuxjdk7では、UTF-8がデフォルトの文字セットであるという印象を常に受け​​ていました。

ありがとう

4

4 に答える 4

39

それは少し複雑です...

Javaは、デフォルトの文字エンコーディングを使用して、String.getBytes() を使用してバイトを返そうとします。

  • デフォルトの文字セットは、システムの file.encoding プロパティによって提供されます。
  • これはキャッシュされ、JVM の起動後に System.setProperty(..) を介して変更しても意味がありません。
  • file.encoding プロパティが既知の文字セットにマップされない場合は、UTF-8 が指定されます。

.... ここがトリッキーな部分です (おそらく決して出てこないでしょう) ....

システムがデフォルトの文字セット (UTF-8 または別の文字セット) を使用して文字列をデコードまたはエンコードできない場合は、ISO-8859-1 にフォールバックします。フォールバックが機能しない場合、システムは失敗します!

.... 本当に... (あえぎ!) ... 指定した文字セットが使用できず、UTF-8 または ISO-8859-1 も使用できない場合、クラッシュする可能性がありますか?

はい。StringCoding.encode(...) メソッドの Java ソース コメントの状態:

// ISO-8859-1 (必要なエンコーディング) が見つからない場合は、インストールに深刻な問題があります。

...そして、 System.exit(1) を呼び出します


では、なぜ getBytes() メソッドで意図的に ISO-8859-1 にフォールバックするのでしょうか?

可能性は低いですが、ユーザーの JVM が UTF-8 または JVM の起動時に指定された文字セットでのデコードとエンコードをサポートしていない可能性があります。

では、getBytes() の際に String クラスでデフォルトの文字セットが適切に使用されていますか?

いいえ、しかし、より良い質問は...


String.getBytes() は約束したものを提供しますか?

Javadoc で定義されている契約は正しいです。

この文字列をデフォルトの文字セットでエンコードできない場合のこのメソッドの動作は規定されていません。このCharsetEncoderクラスは、エンコーディング プロセスをより詳細に制御する必要がある場合に使用する必要があります。


良いニュース (そして物事を行うためのより良い方法)

「ISO-8859-1」、「US-ASCII」、「UTF-8」、またはバイトを文字列に変換する際に必要な任意の文字セットを明示的に指定することを常にお勧めします。デフォルトの文字セットであり、それが必要なものであることを100%確認しました。

代わりに次の方法を使用してください。

public byte[] getBytes(String charsetName)

システムのデフォルトを見つけるには、次を使用します。

Charset.defaultCharset()

それが役立つことを願っています。

于 2012-09-30T07:22:49.237 に答える
13

パラメーターなしのString.getBytes()方法は、既定では ISO-8859-1 を使用しません。決定できる場合は、デフォルトのプラットフォーム エンコーディングが使用されます。ただし、それが見つからないか、認識されないエンコーディングである場合は、「デフォルトのデフォルト」として ISO-8859-1 にフォールバックします。

実際にこれを目にすることはめったにありません。通常、プラットフォームのデフォルトのエンコーディングは正しく検出されます。

ただし、エンコードまたはデコード操作を実行するたびに、明示的な文字エンコーディングを指定することを強くお勧めします。プラットフォームのデフォルトが必要な場合でも、明示的に指定してください。

于 2012-09-30T07:40:41.327 に答える
5

それは互換性の理由です。

歴史的に、文字セットを指定しない Windows および Unix 上のすべての Java メソッドは、当時は共通のもの、つまり"ISO-8859-1".

Isaac と javadoc で言及されているように、デフォルトのプラットフォーム エンコーディングが使用されます ( Charset.javaを参照)。

594    public static Charset defaultCharset() {
595        if (defaultCharset == null) {
596            synchronized (Charset.class) {
597                String csn = AccessController.doPrivileged(
598                    new GetPropertyAction("file.encoding"));
599                Charset cs = lookup(csn);
600                if (cs != null)
601                    defaultCharset = cs;
602                else
603                    defaultCharset = forName("UTF-8");
604            }
605        }
606        return defaultCharset;
607    }

文字列からバイト、またはバイトから文字列への変換を行うときは、常に文字セットを指定します。

あなたの場合のようにString.getBytes()、文字セットを取らない非推奨のメソッドがまだ見つかったとしても (それらのほとんどは Java 1.1 が登場したときに非推奨になりました)。エンディアンと同様に、プラットフォームの形式は関係ありません。関連するのは、ストレージ形式の規範です。

于 2012-09-30T07:16:34.717 に答える