web-dev-qa-db-ja.com

Java)でbyte []として表されるテキストのエンコーディングを推測する

未知のエンコーディング(通常はUTF-8またはISO-8859-1ですが、必ずしもそうとは限りません)のテキストを表すバイトの配列を考えると、(Javaで)使用される可能性が最も高いエンコーディングの推測を取得するための最良の方法は何ですか?

注目に値する:

  • 追加のメタデータはありません。バイト配列は文字通り唯一の利用可能な入力です。
  • 検出アルゴリズムは明らかに100%正確ではありません。アルゴリズムが正しい場合は、80%以上の場合で十分です。
35
knorv

次のメソッドは、Mozillaのエンコーディング検出ライブラリのJavaポートである juniversalchardet を使用して問題を解決します。

public static String guessEncoding(byte[] bytes) {
    String DEFAULT_ENCODING = "UTF-8";
    org.mozilla.universalchardet.UniversalDetector detector =
        new org.mozilla.universalchardet.UniversalDetector(null);
    detector.handleData(bytes, 0, bytes.length);
    detector.dataEnd();
    String encoding = detector.getDetectedCharset();
    detector.reset();
    if (encoding == null) {
        encoding = DEFAULT_ENCODING;
    }
    return encoding;
}

上記のコードはテスト済みであり、意図したとおりに機能します。 juniversalchardet-1.0.3.jar をクラスパスに追加するだけです。

juniversalchardetjchardet の両方をテストしました。私の一般的な印象は、juniversalchardetが2つのライブラリのより良い検出精度とより良いAPIを提供するということです。

33
knorv

Apache Tika-コンテンツ分析ツールキット もあります。 mimeタイプを推測でき、エンコーディングを推測できます。通常、推測は非常に高い確率で正しいです。

4
Thomas Mueller

これが私のお気に入りです: https://github.com/codehaus/guessencoding

それはこのように動作します:

  • UTF-8またはUTF-16BOMがある場合は、そのエンコーディングを返します。
  • どのバイトにも上位ビットが設定されていない場合は、ASCIIを返します(または、代わりにデフォルトの8ビットエンコーディングを返すように強制することもできます)。
  • 上位ビットが設定されているバイトがあり、それらがUTF-8の正しいパターンに配置されている場合は、UTF-8を返します。
  • それ以外の場合は、プラットフォームのデフォルトのエンコーディングを返します(たとえば、英語ロケールのWindowsシステムではwindows-1252)。

単純すぎるように聞こえるかもしれませんが、私の日常業務では、90%をはるかに超える精度があります。

4
Alan Moore

Chiの答えは、実際の使用に最も有望であるように思われます。 Joel Spolskyによれば、InternetExplorerは当時周波数ベースの推測アルゴリズムを使用していたことを付け加えたいと思います。

http://www.joelonsoftware.com/articles/Unicode.html

大まかに言えば、すべての想定されるテキストがコピーされ、考えられるすべてのエンコーディングで解析されます。言語の平均的な単語(および文字?)の頻度プロファイルに最もよく適合する構文解析が勝ちます。 jchardetが同じ種類のアプローチを使用しているかどうかはすぐにはわかりません。そのため、念のためにこれについて言及したいと思いました。

1
Rooke

チェックアウト jchardet

0
Chi