19

大規模なデータセットには、次のようなデータがあります。

"guide (but, yeah, it’s okay to share it with ‘em)."

16 進エディターでファイルを開き、生のバイト データを文字エンコード検出アルゴリズム ( http://code.google.com/p/juniversalchardet/ ) で実行すると、UTF-8 として確実に検出されます。

データのソースが元の文字セットを誤って解釈し、受け取った出力として有効な UTF-8 を書き込んだようです。

できる限りデータを検証したいと思います。検証に役立つ可能性のあるヒューリスティック/アルゴリズムはありますか?

4

2 に答える 2

39

文字列を取得したら、それを行うことはできません。生の入力がまだある間に行う必要があります。’文字列を取得すると、非常に脆弱なテストを行わずに、実際に意図された入力であるかどうかを自動的に判断する方法はありません。例えば:

public static boolean isUTF8MisInterpreted( String input ) {
          //convenience overload for the most common UTF-8 misinterpretation
          //which is also the case in your question
      return isUTF8MisInterpreted( input, "Windows-1252");  
}

public static boolean isUTF8MisInterpreted( String input, String encoding) {

    CharsetDecoder decoder = Charset.forName("UTF-8").newDecoder();
    CharsetEncoder encoder = Charset.forName(encoding).newEncoder();
    ByteBuffer tmp;
    try {
        tmp = encoder.encode(CharBuffer.wrap(input));
    }

    catch(CharacterCodingException e) {
        return false;
    }

    try {
        decoder.decode(tmp);
        return true;
    }
    catch(CharacterCodingException e){
        return false;
    }       
}

public static void main(String args[]) {
    String test = "guide (but, yeah, it’s okay to share it with ‘em).";
    String test2 = "guide (but, yeah, it’s okay to share it with ‘em).";
    System.out.println( isUTF8MisInterpreted(test)); //true
    System.out.println( isUTF8MisInterpreted(test2)); //false

}

まだ生の入力にアクセスできる場合は、バイト配列が完全に有効な utf-8 バイト シーケンスになるかどうかを次のように確認できます。

public static boolean isValidUTF8( byte[] input ) {

    CharsetDecoder cs = Charset.forName("UTF-8").newDecoder();

    try {
        cs.decode(ByteBuffer.wrap(input));
        return true;
    }
    catch(CharacterCodingException e){
        return false;
    }       
}

ストリームで CharsetDecoder を使用することもできます。デフォルトでは、指定されたエンコーディングで無効なバイトが検出されるとすぐに例外がスローされます。

于 2013-01-09T14:04:05.203 に答える