3

ファイルのエンコーディング タイプを確認する必要があります。読み取り可能な場合は true を返します。
このSOの回答によると、このロジックをJavaコードに変換しました。しかし、うまくいきません。まさに、コードのこの部分:

if ((buffer[0] & 0xF8) == 0xF0) {
        if (((buffer[1] & 0xC0) == 0x80)
            && ((buffer[2] == 0x80) && ((buffer[3] == 0x80))))
            return true;
    } else if ((buffer[0] & 0xF0) == 0xE0) {
        if (((buffer[1] & 0xC0) == 0x80) && ((buffer[2] & 0xC0) == 0x80))
            return true;
    } else if ((buffer[0] & 0xE0) == 0xC0) {
        if (((buffer[1] & 0xC0) == 0x80))
            return true;
    } return false;

現時点では、100% UTF-8 コードをチェックしているため、これは正しくチェックされません! => 結果としてreturn false.

すべてのコード:

class EncodindsCheck implements Checker {
    private static final int UTF8_HEADER_SIZE = 8;

    @Override
    public boolean check(File currentFile) {
        return isUTF8(currentFile);
    }

    public static boolean isUTF8(File file) {
        // validate input
        if (null == file) {
            throw new IllegalArgumentException("input file can't be null");
        }
        if (file.isDirectory()) {
            throw new IllegalArgumentException(
                    "input file refers to a directory");
        }

        // read input file
        byte[] buffer;
        try {
            buffer = readUTFHeaderBytes(file);
        } catch (IOException e) {
            throw new IllegalArgumentException(
                    "Can't read input file, error = " + e.getLocalizedMessage());
        }

        if ((buffer[0] & 0xF8) == 0xF0) {
            if (((buffer[1] & 0xC0) == 0x80)
                && ((buffer[2] == 0x80) && ((buffer[3] == 0x80))))
                return true;
        } else if ((buffer[0] & 0xF0) == 0xE0) {
            if (((buffer[1] & 0xC0) == 0x80) && ((buffer[2] & 0xC0) == 0x80))
                return true;
        } else if ((buffer[0] & 0xE0) == 0xC0) {
            if (((buffer[1] & 0xC0) == 0x80))
                return true;
        }

        return false;
    }

    private static byte[] readUTFHeaderBytes(File input) throws IOException {
        byte[] buffer = new byte[UTF8_HEADER_SIZE];
        // read data
        FileInputStream fis = new FileInputStream(input);
        fis.read(buffer);
        fis.close();
        return buffer;
    }
}

質問:

  • このチェックが機能しないのはなぜですか?
  • このチェック検出をこの方法で (UTF-8 文字のシーケンスとして) 解決するにはどうすればよいですか?
  • 他の文字セット ( UTF-16 など)を確認するにはどうすればよいですか?
4

1 に答える 1

2

UTF-8 のコード ポイントの長さは、1、2、3、または 4 バイトです。

すべてのコード ポイントが U+0000 から U+007F の範囲にある場合は、isUTF8false が返されます。この場合、ファイルは多数のエンコーディング (UTF-8、ASCII、ANSI エンコーディングなど) に対して有効です。

あなたの UTF-8 チェックは、最初のコード ポイントが U+007F より上にあることを運に任せています。

少なくとも例として、より包括的なエンコーディング検出 API をご覧になることをお勧めします。


fis.read(buffer);が配列を満たすことは保証されていないことに注意してください。型コントラクトでは、読み取ったバイト数の戻り値を検査する必要があります。

于 2013-03-08T16:31:34.263 に答える