判斷文件是否爲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字符(該字符由多個字節表示)中的第一個字節,而且該字符由四個字節表示;

經過二進制表示以下:spa

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開頭,表明六位)code

符合以上規則的,就表明爲符合utf8編碼規則,不然爲不符合blog

代碼實現以下:ci

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;
    }
}
相關文章
相關標籤/搜索