判断文件是否为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;
    }
}

 

posted on 2014-03-13 10:51  谭英智  阅读(3076)  评论(0编辑  收藏  举报

导航