この問題に対して非常に多くの複雑な解決策が見られた理由は、定義上、解決できないためです。テキストの文字列をエンコードするプロセスは非決定論的です。テキストとエンコーディングのさまざまな組み合わせを構築して、同じバイト ストリームを生成することができます。したがって、厳密に論理的に言えば、バイト ストリームからエンコーディング、文字セット、およびテキストを特定することはできません。
実際には、ヒューリスティック手法を使用して「十分に近い」結果を達成することが可能です。これは、実際に遭遇するエンコーディングのセットが有限であり、十分に大きなサンプルを使用して、プログラムが最も可能性の高いエンコーディングを決定できるためです。 . 結果が十分かどうかは、アプリケーションによって異なります。
ユーザー生成データの問題についてコメントしたいと思います。Web ページから投稿されたすべてのデータには、既知のエンコーディングがあります (POST には、開発者がページ用に定義したエンコーディングが付属しています)。ユーザーがテキストをフォーム フィールドに貼り付けると、ブラウザーは、ソース データのエンコード (オペレーティング システムで認識される) とページのエンコードに基づいてテキストを解釈し、必要に応じてトランスコードします。サーバーでエンコーディングを検出するには遅すぎます。これは、ブラウザーが想定されたエンコーディングに基づいてバイト ストリームを変更した可能性があるためです。
たとえば、ドイツ語のキーボードで Ä の文字を入力し、UTF-8 でエンコードされたページに投稿すると、2 バイト (xC3 x84) がサーバーに送信されます。これは、文字 C および d を表す有効な EBCDIC ストリングです。これは、2 文字の ã と „ を表す有効な ANSI 文字列でもあります。ただし、何を試しても、ANSI でエンコードされた文字列をブラウザー フォームに貼り付けて、それが UTF-8 として解釈されることを期待することはできません。これは、オペレーティング システムが ANSI を貼り付けていることを認識しているためです ( ANSI でエンコードされたテキスト ファイルを作成した Textpad からのテキスト) を UTF-8 にトランスコードすると、バイト ストリーム xC3 x83 xE2 x80 x9E になります。
私の要点は、ユーザーがガベージを投稿できた場合、それはおそらく、クライアントが文字セット、エンコーディングなどを適切にサポートしていなかったため、ブラウザーフォームに貼り付けられた時点ですでにガベージだったためです。文字エンコーディングは非決定論的であるため、そのような状況を明らかにする簡単な方法が存在するとは期待できません。
残念ながら、アップロードされたファイルには問題が残ります。私が見る唯一の信頼できる解決策は、ユーザーにファイルのセクションを表示し、それが正しく解釈されたかどうかを尋ね、そうなるまでさまざまなエンコーディングを繰り返すことです。
または、さまざまな言語での特定の文字の出現を調べるヒューリスティックな方法を開発することもできます。2 バイトの xC3 x84 を含むテキスト ファイルをアップロードしたとします。他の情報はありません。ファイルには 2 バイトしかありません。このメソッドは、文字 Ä がドイツ語のテキストでかなり一般的であることがわかりますが、文字 Ã と „ はどの言語でも一般的ではないため、ファイルのエンコーディングが実際に UTF-8 であると判断できます。この概算は、そのような発見的方法が対処しなければならない複雑さのレベルであり、使用できる統計的および言語学的事実が多ければ多いほど、結果の信頼性が高くなります。