• 根据字节流判断内容是否使用UTF-8编码


    问题:

    只有一个文本内容,文本没有BOM头,怎样才能判断当前文本是否使用UTF-8编码输出呢?

    思路:

    我们都知道使用UTF-8编码输出中文是有多个字节,而且从unicode码转换成UTF-8输出有固定规则,那我们是否可以判断字节流里面是否有满足UTF-8规则的字节串来判断内容是否使用UTF-8编码呢?答案是可以,但不完美。

    通过查询https://en.wikipedia.org/wiki/UTF-8,我们得知UTF-8是通过如下规则将对unicode进行编码,如果在字节流中发现连续字节满足此规则,是否就可以判断到内容就是UTF-8编码后的结果呢?

    Bits of
    code point
    First
    code point
    Last
    code point
    Bytes in
    sequence
    Byte 1Byte 2Byte 3Byte 4Byte 5Byte 6
      7 U+0000 U+007F 1 0xxxxxxx
    11 U+0080 U+07FF 2 110xxxxx 10xxxxxx
    16 U+0800 U+FFFF 3 1110xxxx 10xxxxxx 10xxxxxx
    21 U+10000 U+1FFFFF 4 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
    26 U+200000 U+3FFFFFF 5 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
    31 U+4000000 U+7FFFFFFF 6 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx

      

      

    编码并验证:

      

    package cn.com.demo.util;
    
    import java.io.UnsupportedEncodingException;
    
    public class Utf8Util {
        
        /**
         * UTF-8编码规则
        Bits of code point    First code point    Last code point    Bytes in sequence    Byte 1    Byte 2    Byte 3    Byte 4    Byte 5    Byte 6
        7    U+0000    U+007F    1    0xxxxxxx
        11    U+0080    U+07FF    2    110xxxxx    10xxxxxx
        16    U+0800    U+FFFF    3    1110xxxx    10xxxxxx    10xxxxxx
        21    U+10000    U+1FFFFF    4    11110xxx    10xxxxxx    10xxxxxx    10xxxxxx
        26    U+200000    U+3FFFFFF    5    111110xx    10xxxxxx    10xxxxxx    10xxxxxx    10xxxxxx
        31    U+4000000    U+7FFFFFFF    6    1111110x    10xxxxxx    10xxxxxx    10xxxxxx    10xxxxxx    10xxxxxx
        */
    
        public static boolean isUtf8(byte[] bytes) {
            boolean flag = false;
            if (bytes != null && bytes.length > 0) {
                boolean foundStartByte = false;
                int requireByte = 0;
                for (int i = 0; i < bytes.length; i++) {
                    byte current = bytes[i];
                    //当前字节小于128,标准ASCII码范围
                    if ((current & 0x80) == 0x00) {
                        if (foundStartByte) {
                            foundStartByte = false;
                            requireByte = 0;
                        }
                        continue;
                    //当前以0x110开头,标记2字节编码开始,后面需紧跟1个0x10开头字节
                    }else if ((current & 0xC0) == 0xC0) {
                        foundStartByte = true;
                        requireByte = 1;
                    //当前以0x1110开头,标记3字节编码开始,后面需紧跟2个0x10开头字节
                    }else if ((current & 0xE0) == 0xE0) {
                        foundStartByte = true;
                        requireByte = 2;
                    //当前以0x11110开头,标记4字节编码开始,后面需紧跟3个0x10开头字节
                    }else if ((current & 0xF0) == 0xF0) {
                        foundStartByte = true;
                        requireByte = 3;
                    //当前以0x111110开头,标记5字节编码开始,后面需紧跟4个0x10开头字节
                    }else if ((current & 0xE8) == 0xE8) {
                        foundStartByte = true;
                        requireByte = 4;
                    //当前以0x1111110开头,标记6字节编码开始,后面需紧跟5个0x10开头字节
                    }else if ((current & 0xEC) == 0xEC) {
                        foundStartByte = true;
                        requireByte = 5;
                    //当前以0x10开头,判断是否满足utf8编码规则
                    }else if ((current & 0x80) == 0x80) {
                        if (foundStartByte) {
                            requireByte--;
                            //出现多个0x10开头字节,个数满足,发现utf8编码字符,直接返回
                            if (requireByte == 0) {
                                return true;
                            }
                        //虽然经当前以0x10开头,但前一字节不是以0x110|0x1110|0x11110肯定不是utf8编码,直接返回
                        }else {
                            return false;
                        }
                    //发现0x8000~0xC000之间字节,肯定不是utf8编码
                    }else {
                        return false;
                    }
                }
            }
            return false;
        }
        
        public static void main(String[] args) throws UnsupportedEncodingException {
            String str = "<a href="http://www.baidu.com">百度一下</a>";
            System.out.println(Utf8Util.isUtf8(str.getBytes("utf-8"))); 
            System.out.println(Utf8Util.isUtf8(str.getBytes("gbk"))); 
        }
    
    }

       

    结果:

    基本可以识别出个大概,但存在以下问题:只判断到满足1次规则就直接返回,有可能是无规则字节流(图片字节流或者其它)刚好满足以上需求,但实际不是UTF-8编码结果。

      

  • 相关阅读:
    [JAVA]基本数据类型
    [JAVA]生成随机数
    Java编写POST请求
    修改Tomcat的端口
    Windows设置Tomcat的管理员的用户和密码
    JMeter环境搭建
    LoadRunner通过火狐浏览器录制脚本后,进行回放时,回放脚本很慢
    JVM性能分析与优化:
    Web服务器性能监控分析与优化
    LoadRunner性能测试结果分析
  • 原文地址:https://www.cnblogs.com/deacon/p/4886738.html
Copyright © 2020-2023  润新知