• 判断文件是否为UTF8编码


    utf8的规则比较简单:

    • 对于UTF-8编码中的任意字节B,如果B的第一位为0,则B为ASCII码,并且B独立的表示一个字符;
    • 如果B的第一位为1,第二位为0,则B为一个非ASCII字符(该字符由多个字节表示)中的一个字节,并且不为字符的第一个字节编码;
    • 如果B的前两位为1,第三位为0,则B为一个非ASCII字符(该字符由多个字节表示)中的第一个字节,并且该字符由两个字节表示;
    • 如果B的前三位为1,第四位为0,则B为一个非ASCII字符(该字符由多个字节表示)中的第一个字节,并且该字符由三个字节表示;
    • 如果B的前四位为1,第五位为0,则B为一个非ASCII字符(该字符由多个字节表示)中的第一个字节,并且该字符由四个字节表示;

    通过二进制表示如下:

    0xxxxxxx (一位的情况,为ASCII)
    110xxxxx 10xxxxxx (110开头,代表两位)
    1110xxxx 10xxxxxx 10xxxxxx (1110开头代表三位)
    11110xxx 10xxxxxx 10xxxxxx 10xxxxxx (11110开头代表四位)
    111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx (111110开头,代表五位)
    1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx (1111110开头,代表六位)

    符合以上规则的,就代表为符合utf8编码规则,否则为不符合

    代码实现如下:

    bool isUTF8(char* rawtext) 
    {
        int score = 0;
        int i, rawtextlen = 0;
        int goodbytes = 0, asciibytes = 0;
    
        rawtextlen = strlen(rawtext);
        for (i = 0; i < rawtextlen; i++) 
        {
            if ((rawtext[i] &  0x7F) == rawtext[i]) 
            { 
                //最高位是0的ASCII字符
                //一位编码的情况
                asciibytes++;
            } 
            else if (-64 <= rawtext[i] && rawtext[i] <= -33
                    //两位编码的情况,第一位11000000--11011111
                    //后一位跟10000000--10111111
                    &&i + 1 < rawtextlen 
                    && -128 <= rawtext[i + 1] && rawtext[i + 1] <= -65) 
            {
                goodbytes += 2;
                i++;
            } 
            else if (-32 <= rawtext[i]&& rawtext[i] <= -17
                    //三位编码的情况,第一位11100000--11101111
                     //后两位跟10000000--10111111
                    &&i + 2 < rawtextlen 
                    && -128 <= rawtext[i + 1] && rawtext[i + 1] <= -65 
                    && -128 <= rawtext[i + 2] && rawtext[i + 2] <= -65) 
            {
                goodbytes += 3;
                i += 2;
            }
            else if(-16 <= rawtext[i]&& rawtext[i] <= -9
                //四位编码的情况,第一位11110000--11110111
                //后三位跟10000000--10111111
                &&i + 3 < rawtextlen 
                &&  -128 <= rawtext[i + 1] && rawtext[i + 1] <= -65 
                && -128 <= rawtext[i + 2] && rawtext[i + 2] <= -65
                && -128 <= rawtext[i + 3] && rawtext[i + 3] <= -65)
                
            {
                goodbytes += 4;
                i += 3;
            }
            else if(-8 <= rawtext[i]&& rawtext[i] <= -5
                //五位编码的情况,第一位11111000--11111011
                //后四位跟10000000--10111111
                &&i + 4 < rawtextlen 
                &&  -128 <= rawtext[i + 1] && rawtext[i + 1] <= -65 
                && -128 <= rawtext[i + 2] && rawtext[i + 2] <= -65
                && -128 <= rawtext[i + 3] && rawtext[i + 3] <= -65
                && -128 <= rawtext[i + 4] && rawtext[i + 4] <= -65)
            {
                goodbytes += 5;
                i += 4;
            }
            else if(-4 <= rawtext[i]&& rawtext[i] <= -3
                //六位编码的情况,第一位11111100--11111101
                //后五位跟10000000--10111111
                &&i + 5 < rawtextlen 
                &&  -128 <= rawtext[i + 1] && rawtext[i + 1] <= -65 
                && -128 <= rawtext[i + 2] && rawtext[i + 2] <= -65
                && -128 <= rawtext[i + 3] && rawtext[i + 3] <= -65
                && -128 <= rawtext[i + 4] && rawtext[i + 4] <= -65
                && -128 <= rawtext[i + 5] && rawtext[i + 5] <= -65)
            {
                goodbytes += 6;
                i += 5;
            }
        }
        if (asciibytes == rawtextlen) 
        {
            return true;
        }
        score = 100 * goodbytes / (rawtextlen - asciibytes);
        //如果匹配率达到98%以上,则成功
        //允许一部分脏数据
        if (score > 98) 
        {
            return true;
        } 
        else if (score > 95 && goodbytes > 30) 
        {
            return true;
        } 
        else 
        {
            return false;
        }
    }
  • 相关阅读:
    前端 fetch 通信
    编写高质量的JavaScript代码(一)
    Redis学习笔记1-Redis的介绍和认识
    gitignore不起作用解决的方法
    【我的面经】说说简历的细节——软件开发岗位
    菜鸟的mongoDB学习---(七)MongoDB 备份(mongodump)与恢复(mongorerstore)
    HDU 4927 Series 1
    树状数组求第K小值 (spoj227 Ordering the Soldiers &amp;&amp; hdu2852 KiKi&#39;s K-Number)
    git和SVN的差别
    KVM-Introduce
  • 原文地址:https://www.cnblogs.com/kukafeiso/p/3598059.html
Copyright © 2020-2023  润新知