1 つの好奇心として、JVM が元のデフォルトの文字セットをどのように知っているのだろうか...
初期のデフォルト文字セットを決定するために JVM が使用するメカニズムは、プラットフォーム固有です。UNIX / UNIX 系システムでは、LANG および LC_* 環境変数によって決定されます。を参照してくださいman locale
。
えっと..このコマンドは、特定の OS のデフォルトの文字セットを確認するために使用されます。
それは正しいです。しかし、マニュアル エントリには、デフォルトのエンコーディングが環境変数によってどのように決定されるかが記述されているため、そのことについて説明しました。
振り返ってみると、これは元のコメントの意図とは異なる場合がありますが、これがプラットフォームのデフォルトのエンコーディングの指定方法です。(また、個々のファイルの「デフォルト文字セット」の概念は無意味です。以下を参照してください。)
10 個の Java ソース ファイルがあり、その半分が UTF-8 として保存され、残りが UTF-16 として保存されているとします。コンパイル後、それら (クラス ファイル) を別の OS プラットフォームに移動します。 ? デフォルトの文字セット情報は Java クラス ファイルに含まれますか?
これはかなり混乱した一連の質問です。
テキスト ファイルには既定の文字セットがありません。文字セット/エンコーディングがあります。
非テキスト ファイルには文字エンコーディングがまったくありません。概念は無意味です。
テキスト ファイルの文字エンコーディングを判断する 100% 信頼できる方法はありません。
ファイルのエンコーディングを Java コンパイラに伝えないと、それがプラットフォームのデフォルトのエンコーディングであると見なされます。コンパイラは、あなたを推測しようとしません。エンコーディングが正しくない場合、コンパイラは間違いに気付く場合と気付かない場合があります。
バイトコード (".class") ファイルはバイナリ ファイルです (2 を参照)。
文字リテラルと文字列リテラルが「.class」ファイルにコンパイルされると、プラットフォームのデフォルトのエンコーディングやその他の影響を受けない方法で表現されるようになりました。
コンパイル時にソース ファイルのエンコーディングを間違えた場合、「.class」ファイル レベルで修正することはできません。唯一の選択肢は、戻ってクラスを再コンパイルし、Java コンパイラに正しいソース ファイルのエンコーディングを伝えることです。
「10 個の Java ソース ファイルがあり、その半分が UTF-8 で保存され、残りが UTF-16 で保存されているとします。」 .
ただそれをしないでください!
- エンコーディングが混在するソース ファイルを保存しないでください。あなたは自分自身を狂わせるでしょう。
- ファイルをUTF-16で保存する正当な理由はまったくありません...
それで、人々は「プラットフォームに依存する」と言っていますが、それはソースファイルに関連しているのでしょうか?
プラットフォーム依存とは、オペレーティング システム、JVM のベンダーとバージョン、ハードウェアなどに依存する可能性があることを意味します。
ソースファイルとは必ずしも関係ありません。(特定のソース ファイルのエンコーディングは、既定の文字エンコーディングとは異なる場合があります。)
そうでない場合、上記の現象をどのように説明できますか? とにかく、上記の混乱は私の質問を「クラスファイルにエンコード情報が含まれていない可能性があるため、ソースファイルをクラスファイルにコンパイルした後にどうなるか」に拡張され、結果は「プラットフォーム」に依存しますが、ソースファイルには依存しなくなりました?」
プラットフォーム固有のメカニズム (環境変数など) によって、Java コンパイラがデフォルトの文字セットと見なすものが決まります。これをオーバーライドしない限り (たとえば、コマンド ラインで Java コンパイラにオプションを指定するなど)、Java コンパイラはそれをソース ファイルの文字セットとして使用します。ただし、これはソース ファイルの正しい文字エンコーディングではない可能性があります。たとえば、異なるデフォルト文字セットを持つ別のマシンでそれらを作成した場合。また、Java コンパイラが間違った文字セットを使用してソース ファイルをデコードすると、「.class」ファイルに間違った文字コードが挿入される可能性があります。
「.class」ファイルはプラットフォームに依存しません。しかし、ソース ファイルの正しいエンコーディングを Java コンパイラに伝えなかったために、それらが正しく作成されなかった場合、".class" ファイルには間違った文字が含まれます。
「個々のファイルの「デフォルトの文字セット」の概念は無意味です」というのはなぜですか?
本当だから言います!
デフォルトの文字セットとは、指定しない場合に使用される文字セットを意味します。
しかし、テキスト ファイルを正しく保存する方法を制御できますか? メモ帳を使用しても、エンコーディングを選択するオプションがあります。
それは正しいです。これで、ファイルに使用する文字セットをメモ帳に伝えることができます。TELL を指定しない場合、メモ帳はデフォルトの文字セットを使用してファイルを書き込みます。
メモ帳には、テキスト ファイルを読み取るときに文字エンコーディングが何であるかを推測するための黒魔術が少しあります。基本的に、ファイルの最初の数バイトを調べて、UTF-16 バイト オーダー マークで始まるかどうかを確認します。検出された場合、UTF-16、UTF-8 (Microscoft 製品によって生成されたもの)、および「その他」をヒューリスティックに区別できます。しかし、異なる「その他の」文字エンコーディングを区別することはできず、BOM マーカーで始まらないファイルを UTF-8 として認識しません。(UTF-8 ファイルの BOM は Microsoft 固有の規約です ... Java アプリケーションがファイルを読み取り、BOM 文字をスキップすることを認識していない場合、問題が発生します。)
とにかく、問題はソースファイルを書くことではありません。これらは、Java コンパイラーが不適切な文字エンコーディングでソース ファイルを読み取るときに発生します。