3

我需要检查文件的编码类型。如果它是可读的,则返回 true。
根据这个SO answer,我在 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 范围内,则isUTF8返回 false。在这种情况下,该文件将适用于大量编码(UTF-8、ASCII、ANSI 编码等)

您的 UTF-8 检查相信第一个代码点高于 U+007F 是幸运的。

我建议你看一个更全面的编码检测 API,至少作为一个例子。


注意fis.read(buffer);不保证填充数组;类型协定要求您检查读取的字节数的返回值。

于 2013-03-08T16:31:34.263 回答