文字セット名が定数ではないのはなぜですか?


211

文字セットの問題はそれ自体が混乱して複雑ですが、その上、文字セットの正確な名前を覚えておく必要があります。ですよ"utf8"ね?または"utf-8"?それとも"UTF-8"?インターネットでコードサンプルを検索すると、上記のすべてが表示されます。なぜそれらを名前付き定数にして使用しCharset.UTF8ないのですか?


19
+1:これもいつも私を悩ませていました。MessageDigest#getInstance()ちなみに同じ話が続きます。
BalusC 2009年

2
実際の答えは、Sunの担当者に尋ねる必要があります。幸運を祈ります:-)
スティーブンC

1
Stephen C:公開メーリングリストで議論されたと思います。-日曜日の誰か。
トム・ホーティン-2009年

回答:


160

質問に対する簡単な答えは、使用可能な文字セット文字列はプラットフォームごとに異なるということです。

ただし、存在する必要があるのは6つなので、定数はずっと前に作成されている可能性があります。彼らがそうでなかった理由がわかりません。

JDK 1.4は、Charsetタイプを導入することで素晴らしい成果を上げました。この時点では、Charsetインスタンスを使用して全員を取得することを目的としているため、もはやString定数を提供する必要はありませんでした。それでは、なぜ6つの標準Charset定数を提供しないのでしょうか。マーティンブーフホルツがたまたま私の隣に座っているので、彼に尋ねたところ、当時特に問題はなかったということを除いて、それほど大きな理由はなかったと述べました。 Charsetを受け入れます。Charsetのオーバーロードは通常、わずかにパフォーマンスが低下しました。

JDK 1.6でのみ、Charsetオーバーロードを備えたすべてのものが最終的に装備されたのは残念です。そして、この逆方向のパフォーマンス状況はまだ存在しています(理由は信じられないほど奇妙で説明できないのですが、セキュリティに関連しています!)。

要するに、独自の定数を定義するか、Tony the PonyがリンクしているGuavaのCharsetsクラスを使用するだけです(そのライブラリはまだ実際にはまだリリースされていません)。

アップデート:StandardCharsetsこのクラスは、JDK 7です。


グアバのリリース(アルファ/ベータ/何でも)があるときのアイデアは?プロジェクトのホームページは、これについて少し節度があります。
Jonik、2009年

それがなくなるまで私にとって七面鳥はありません!
Kevin Bourrillion、2009年

信じられないほど奇妙で理由は説明できませんが、セキュリティに関連しています。カスタム文字セットを介して変更可能な文字列を作成できますが、文字列(実際には文字セットを検索する)よりも高速に機能する可能性があります。String(byte bytes[], int offset, int length, Charset charset)実装方法の省略/無視です。実際、大きなbyte []から小さな文字列を作成する場合、パフォーマンスへの影響はそれほど大きくありません。
bestsss 2013年

7
ずるいです!あなたはそのような素晴らしいリソースにアクセスできます。=(私はあなたがかつて言った別の答えを見ました、「ええ、それで私はそれについてジョシュ[ブロック]に尋ねました...」
kevinarpe 2013

PrintStreamはCharsetをサポートしていません
rofrol 2014年

102

2年後、Java 7のStandardCharsetsは現在、6つの標準文字セットの定数を定義しています。

Java 5/6で行き詰まっている場合は、Kevin BourrillionとJon Skeetによって提案されているように、GuavaのCharsets定数を使用できます。


29

私はそれよりもはるかに良いことができると主張します...なぜ保証された利用可能な文字セットに直接アクセスできないのですか?文字列としての名前ではなく、Charset.UTF8への参照にする必要がありCharsetます。そうすれば、私たちはあちこちで処理UnsupportedEncodingExceptionする必要がなくなります。

また、.NETはどこでもデフォルトでUTF-8に設定することで、より優れた戦略を選択したと思います。次に、「オペレーティングシステムのデフォルト」エンコーディングプロパティに単純に名前を付けることで失敗しました。Encoding.Defaultこれ .NET自体のデフォルトではありません :(

Javaの文字セットサポートについての認可に戻る-なぜFileWriter/ FileReaderをとるコンストラクタがないのCharsetですか?基本的にそれらはその制限のためにほとんど役に立たないクラスです-あなたはほとんど常に出力のためにInputStreamReadera FileInputStreamまたは同等のものを必要とします:(

看護師、看護師-私の薬はどこですか?

編集:これは実際には質問に答えていないことが私に起こります。本当の答えは、おそらく「誰もそれについて考えたことがない」または「関係者がそれが悪い考えだと思った」のいずれかです。名前または文字セットを提供する社内ユーティリティクラスは、コードベースの重複を避けることを強くお勧めします...または、この回答が最初に書かれたときにGoogleで使用したものを使用することもできます。(Java 7以降では、StandardCharsets代わりに使用することに注意してください。)


2
+1。しかし、遅延読み込みを可能にするためのフィールドではなくメソッドとして(おそらく、UTF-8が必要になるでしょうが、他にもいくつかの文字セットがあり、それらに同様の機能が必要になる場合があります)。残念ながら、これは決定を下す人にはあまり人気がないようです。
トム・ホーティン-2009年

私はメソッドで十分満足していますが、これらの非常に少数の文字セットを熱心にロードしても、大きなコストにならないことを願っています。
Jon Skeet、

1
熱心なクラスの読み込みを停止するための十字軍にいます。/「UTF-8」のJDKを検索したところです。165個のファイルで270件の一致が見つかりました。その多くは古いアパッチジャンクにありますが(私のチームによる貢献だと思います)。
トム・ホーティン-2009年

1
@tackline:熱心なクラスローディングは、時間の経過とともに増えるものの1つだと思います。ここにいくつかのクラス、そこにいくつかのクラス-個々に十分に無害に聞こえる-は大きな違いを生む可能性があります。
Jon Skeet、

Guava Charsetsへの最後のリンクは壊れています。
LarsH

28

Java 1.7の場合

import java.nio.charset.StandardCharsets

例: StandardCharsets.UTF_8 StandardCharsets.US_ASCII


5

エンコーディングAPIの現在の状態では、望ましいことが残っています。Java 6のAPIの一部は受け付けませんCharset(文字列の代わりにloggingdom.lsPrintStream、他の人があるかもしれません)。エンコーディングが標準ライブラリの異なる部分に対して異なる正規名を持っていることになっていることは役に立ちません。

私は物事がそれらがどこにあるかを理解することができます。それらを修正する方法について素晴らしいアイデアがあるかどうかはわかりません。


余談として...

ここでSunのJava 6実装の名前を調べることができます。

UTF-8の場合、正規値は"UTF-8"for java.nioおよび"UTF8"for java.langおよびjava.ioです。仕様でサポートするJREが必要なエンコーディングは次のとおりです。US-ASCII。ISO-8859-1; UTF-8; UTF-16BE; UTF-16LE; UTF-16


2
クラスは「PrintWriterクラスはバイトではなく文字の書き込みを必要とする状況で使用する必要があります」と明確に述べているので、私はPrintStreamの1つを惜しみません。(これは、すべての状況のようです...)
Kevin Bourrillion、2009年

2

私はずっと前に、UTF_8、ISO_8859_1、およびUS_ASCII文字セット定数を使用してユーティリティクラスを定義しました。

また、(2年以上)前に、いくつかの長い時間は私が間の単純な性能試験を行ったnew String( byte[], Charset )new String( byte[], String charset_name )し、後者の実装があることを発見した結果大幅に高速。ソースコードの内部を確認すると、実際にはまったく異なるパスをたどっていることがわかります。

そのため、同じクラスにユーティリティを含めました

public static String stringFromByteArray (
    final byte[] array,
    final Charset charset
)
{
    try
    {
        return new String( array, charset.name( ) )
    }
    catch ( UnsupportedEncodingException ex )
    {
        // cannot happen
    }
}

String(byte []、Charset)コンストラクタが同じことをしないのはなぜですか。


1
Charset必要が登録されていないので、例外が発生する可能性があります。IIRC、既知の良好なCharset実装(余分なコピーを排除)を高速化するためにJDK7にいくつかの変更がありました。
トム・ホーティン-タックライン2009年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.