IT技术博客大学习 共学习 共进步

区分一个包含汉字的字符串是 UTF-8 还是 GBK

云风的 BLOG 2010-07-07 14:48:25 浏览 4,041 次

今天检查 svn 仓库,发现又有同学没按规定提交包含汉字的代码。我们规定,所有源文件中包含的汉字必须使用 UTF-8 编码方式,而不能使用 GBK 。

总这么人工检查也不是个事。所以我想写一个 svn 的钩子,在提交前检查。在仓库的 hooks/pre-commit.teml 加一行检查脚本应该就可以了。

我想用正则表达式匹配一下,可是想了想又觉得 UTF-8 和 GBK 的编码集有点交集,不太好做。btw, google 了一下,的确有人写过特定编码的正则表达式

继续 google ,找到一篇跟我需求有点类似的文章UTF-8编码检测失败特例。看了正文,觉得不太靠谱,然后继续看回复,觉得这方法可行。

然后定睛一看,原来文章是孟岩写的,回复是我自己三年多前回复在他的 blog 上的。 -_-

打算还是自己写个小程序做检查,不用现成工具了。

具体算法复制回这里:

cloudwu 发表于2007-01-05 00:49:51 IP: 218.72.15.*

如果想区分一个完整的字符串是 GBK 还是 UTF8 其实蛮简单的。虽然做不到 100% 有效,但也比上面的方法强许多。

UTF8 是兼容 ascii 的,所以 0~127 就和 ascii 完全一致了。

gbk 的第一字节是高位为 1 的,第 2 字节可能高位为 0 。这种情况一定是 gbk ,因为 UTF8 对 >127 的编码一定每个字节高位为 1 。

另外,对于中文,UTF8 一定编码成 3 字节。(似乎亚洲文字都是,UTF8 中双字节好象只用于西方字符集)

所以型如 110***** 10****** 的,我们一概看成 gbk/gb2312 编码。这就解决了“位”的问题。

汉字以及汉字标点(包括日文汉字等),在 UTF8 中一定被编码成:1110**** 10****** 10******

连续汉字数量不是 3 的倍数的 gb2312 编码的汉字字符串一定不会被误认为 UTF8 。用了一些gbk 扩展字,或是插入了一些 ascii 符号的字符串也几乎不会被认为是 UTF8 。

一般说来,只要汉字稍微多几个,gbk 串被误认为 UTF8 的可能性极其低。(只需要默认不使用 UTF8 中双字节表示的字符)可能性低,这里还有另外一个原因。UTF8 中汉字编码的第一个字节是 1110**** ,这处于汉字的 gb2312 中二级汉字(不常用汉字,区码从 11011000 开始)的编码空间。一般是一些生僻字才会碰上。

建议继续学习

  1. ORACEL RAC 字符集 (阅读 5,362)
  2. linux下vim的编译以及终端乱码的最终解决方案 (阅读 4,741)
  3. oracle查看字符集 修改字符集 (阅读 3,842)
  4. 如何在MYSQL5.5只支出utf8环境下正常使用GBK网站 (阅读 3,702)
  5. java中文乱码解决之道(一)—–认识字符集 (阅读 3,642)
  6. mysql latin1转utf8 的两种方法 (阅读 3,341)
  7. mysql字符集和校验规则概念小介 (阅读 3,242)
  8. mysql字符集与校验规则的设置 (阅读 3,061)
  9. mysql连接通道中的字符集和校验规则 (阅读 2,941)
  10. java中文乱码解决之道(二)—–字符编码详解:基础知识 + ASCII + GB** (阅读 2,881)