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; } }