Java读取文件,判断是否UTF-8的解决方案

本文介绍了一种通过读取文件头部字节来判断文件编码的方法,特别是对于无BOM的UTF-8编码文件,提供了一段Java代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题

Java的文件输入流InputStreamReader虽然有getEncode方法,但是实际上这个方法读出来都是UTF-8格式,这是个bug。
因此只有自行判断

有bom的UTF-8

首先有bom的UTF-8可以通过文件的前3个byte来确定文件的编码,比较简单:
先读取文件前面的byte

inputStream = new FileInputStream(file);
byte[] head = new byte[headSize];
inputStream.read(head);
if (head[0] == -1 && head[1] == -2) {
    code = "UTF-16";
    System.err.println("文件编码错误: " + file.getName() + " : " + code);
} else if (head[0] == -2 && head[1] == -1) {
    code = "Unicode";
    System.err.println("文件编码错误: " + file.getName() + " : " + code);
} else if (head[0] == -17 && head[1] == -69 && head[2] == -65) {
    code = "UTF-8";
} else {
    // 检查无Bom的UTF-8
}

但是实际上我们大多文件是无bom的UTF-8,也就是文件头部没有文件标志的字节,第一个字节就是数据内容。

无bom的UTF-8

网上有很多根据UTF-8的编码规则来判断格式的,可是用于java的都不是很好用。
首先,UTF-8的编码方式:

1字节 0xxxxxxx
2字节 110xxxxx 10xxxxxx
3字节 1110xxxx 10xxxxxx 10xxxxxx
4字节 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
5字节 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
6字节 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx

实际上都在3字节内,没有遇到4字节以上编码的。根据其编码格式我们就可以文件进行一定的验证了,例如:

{
    int i = 0;
    code = "UTF-8 NoBom";
    while (i < headSize - 2) {
        if ((head[i] & 0x00FF) < 0x80) {// (10000000)值小于0x80的为ASCII字符
            i++;
            continue;
        } else if ((head[i] & 0x00FF) < 0xC0) {// (11000000)值在0x80和0xC0之间的,不是开头第一个
            code = "Not UTF-8";
            System.err.println("文件编码错误: " + file.getName() + " : " + code + "1000");
            break;
        } else if ((head[i] & 0x00FF) < 0xE0) {// (11100000)此范围内为2字节UTF-8字符
            if ((head[i + 1] & (0xC0)) != 0x8) {
                code = "Not UTF-8";
                System.err.println("文件编码错误: " + file.getName() + " : " + code + "1100");
                break;
            } else
                i += 2;
        } else if ((head[i] & 0x00FF) < 0xF0) {// (11110000)此范围内为3字节UTF-8字符
            if ((head[i + 1] & (0xC0)) != 0x80 || (head[i + 2] & (0xC0)) != 0x80) {
                code = "Not UTF-8";
                System.err.println("文件编码错误: " + file.getName() + " : " + code + "11100000" + (head[i + 1] & (0xC0)));
                break;
            } else
                i += 3;
        } else {
            code = "Not UTF-8";
            System.err.println("文件编码错误: " + file.getName() + " : " + code + "1111");
            break;
        }
    }
}

然后用这一段替代前一段代码中 // 检查无Bom的UTF-8 的位置.
这种方法还是存在巧合误判的情况,但是headline设置的越大就越不容易出现错误。
另外,由于UTF-8对ASCII字符的编码与ASCII一致,因此如果所有字符都是ASCII,就无法判断是ASCII还是UTF-8无bom格式,使用本文方法会判断为UTF-8 .

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值