这个问题之所以是一个问题,是因为有一些字符串是能够同时符合两种编码规范的,比如:
- “跃” — 他的GB18030编码为2字节 11010100 10111110,而同时也符合utf-8中的两字节的编码规范 110xxxxx 10xxxxxx,类似的汉字还有很多,比如:”珊”
- “跃跃” — 他的utf-8编码为6字节 11101000 10110111 10000011 11101000 10110111 10000011,而同时这也是三个双字节的GB18030的编码(”璺冭穬”),虽然是一些生僻字
因此完全的识别字符串的编码不可能是一个完美(精确)的方案,但我们考虑到下面两个事实:
- utf-8中使用2个字节编码的字符都是一些不常用的字符,通常一个文本中不会全部是这样的字符
- 如果把utf-8编码中超过3字节以上编码的内容按照gb18030的编码理解,得到的通常也是一些生僻字
我们在做一个假设
- 字符串要么符合utf-8编码规范,要么符合gb18030编码规范
就可以得到一个最佳实践:从头扫描一个字符串
- 如果不符合utf-8的规范,认为是gb18030编码
- 如果有符合utf-8规范中的3字节或4字节编码的,认为是utf-8编码
- 如果有符合utf-8规范中的2字节编码的,但是不符合gb18030编码的,认为是utf-8编码
- 如果全部都是符合2字节的utf-8编码,同时也符合gb18030编码的,认为是gb18030编码
我使用php实现了这个检查的函数,代码位于https://github.com/zhangchu/ko中的 Ko_Tool_Str::BIsUtf8($sIn);