判断一段文件是UTF-8编码还是GB2312的编码方式


分类: 算法 cpp   7120人阅读  评论(2)  收藏  举报

对于只包含中文和英文的文本中判断编码方式是非常简单的,中文的编码方式最常用的是GBK,字符集更大的如GBK向下兼容GB2312,其中包含的的很多一部分字符是我们在日常生活中用不到的,因此在实际中我们一般只需要区分GB2312和UTF8编码。这里我只是提供一种可行的方法,如果判断GBK也可以采用类似的方式首先分析一下汉字在GB2312中的编码方式,gb2312规则汉字采用双字节编码其中第一字节161~247,第二字节161~254,其中含有边界条件。而utf8的编码方式可以看如下表示:

  1. <span style="font-family:Arial, Verdana, sans-serif;"><span style="white-space: normal;">  
  2. </span></span>  

代码范围
十六进制
标量值(scalar value)
二进制
UTF-8
二进制十六进制
注释
000000 - 00007F
128个代码
00000000 00000000 0zzzzzzz0zzzzzzz(00-7F)ASCII字符范围,字节由零开始
七个z七个z
000080 - 0007FF
1920个代码
00000000 00000yyy yyzzzzzz110yyyyy(C0-DF) 10zzzzzz(80-BF) 第一个字节由110开始,接着的字节由10开始
三个y;二个y;六个z五个y;六个z
000800 - 00D7FF
00E000 - 00FFFF
61440个代码 [Note 1]
00000000 xxxxyyyy yyzzzzzz1110xxxx(E0-EF) 10yyyyyy 10zzzzzz 第一个字节由1110开始,接着的字节由10开始
四个x;四个y;二个y;六个z四个x;六个y;六个z
010000 - 10FFFF
1048576个代码
000wwwxx xxxxyyyy yyzzzzzz11110www(F0-F7) 10xxxxxx 10yyyyyy 10zzzzzz将由11110开始,接着的字节由10开始
这样我们就可以由编码方式上的差异来进行GB2312和UTF8编码识别,下面给出代码

  1. unsigned int countGBK(const char * str)  
  2. {  
  3.     assert(str != NULL);  
  4.     unsigned int len = (unsigned int)strlen (str);  
  5.     unsigned int counter = 0;  
  6.     unsigned char head = 0x80;  
  7.     unsigned char firstChar, secondChar;  
  8.   
  9.     for (unsigned int i = 0; i < len - 1; ++i)  
  10.     {  
  11.         firstChar = (unsigned char)str[i];  
  12.         if (!(firstChar & head))continue;  
  13.         secondChar = (unsigned char)str[i];  
  14.         if (firstChar >= 161 && firstChar <= 247 && secondChar>=161 && secondChar <= 254)  
  15.         {  
  16.             counter+= 2;  
  17.             ++i;  
  18.         }  
  19.     }  
  20.     return counter;  
  21. }  
  22.   
  23. unsigned int countUTF8(const char * str)  
  24. {  
  25.     assert(str != NULL);  
  26.     unsigned int len = (unsigned int)strlen (str);  
  27.     unsigned int counter = 0;  
  28.     unsigned char head = 0x80;  
  29.     unsigned char firstChar;  
  30.     for (unsigned int i = 0; i < len; ++i)  
  31.     {  
  32.         firstChar = (unsigned char)str[i];  
  33.         if (!(firstChar & head))continue;  
  34.         unsigned char tmpHead = head;  
  35.         unsigned int wordLen = 0 , tPos = 0;  
  36.         while (firstChar & tmpHead)  
  37.         {  
  38.             ++ wordLen;  
  39.             tmpHead >>= 1;  
  40.         }  
  41.         if (wordLen <= 1)continue//utf8最小长度为2  
  42.         wordLen --;  
  43.         if (wordLen + i >= len)break;  
  44.         for (tPos = 1; tPos <= wordLen; ++tPos)  
  45.         {  
  46.             unsigned char secondChar = (unsigned char)str[i + tPos];  
  47.             if (!(secondChar & head))break;  
  48.         }  
  49.         if (tPos > wordLen)  
  50.         {  
  51.             counter += wordLen + 1;  
  52.             i += wordLen;  
  53.         }  
  54.     }  
  55.     return counter;  
  56. }  
  57.   
  58. bool beUtf8(const char *str)  
  59. {  
  60.     <span style="white-space:pre">  </span>unsigned int iGBK = countGBK(str);  
  61.     unsigned int iUTF8= countUTF8(str);  
  62.     if (iUTF8 > iGBK)return true;  
  63.     return false;  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值