酷勤网 – 程序员的那点事!

当前位置:首页 > 编程 > 编程语言 > 正文

UTF-8编码检测失败特例

浏览次数: 2007年12月01日 CSDN博客 字号:

Ruby中进行UTF-8编码检测的方法是String#unpack方法,传入 "U*" 模板。这个模板的意思是把字符串当成一个UTF-8串,分别把每一个Unicode字符转换成对应的代码点并组合为数组。字符串本身确实是UTF-8,则能够转换成功,否则将抛出异常。根据这种行为,给String添加如下实例方法:

  class String
    def utf8?
      unpack("U*") rescue return false
      true
    end
  end

    以上程序在大部分情况下确实正确。但是我发现GB2312编码中,下列汉字的GB2312编码能够通过上面方法的检测,而被误认为是UTF-8串:
 
    位、前、支、校、写、元

    可能还有一些。因此,上述方法不适宜用来对可能包含GB2312编码的中文字串进行UTF-8编码检测。

    注意这不是Ruby的问题,而是不同编码模式导致的本质难题。

    可以做以下实验:
 
    1. 打开notepad,写入一个‘位’字,不回车,直接以ANSI编码保存(注意必须用ANSI编码保存)。

    2. 再次打开这个文件,你会看到显示出来的不是“位”字,而是λ。

    同样,“前、支、校、写、元” 等单字也存在类似现象。

    可见字符串编码检测并不容易。不知有没有什么可靠的方法(除了用Iconv库直试转以外),望知者不吝赐教。

评论

#   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 开始)的编码空间。一般是一些生僻字才会碰上。


#   qiangsheng 发表于2007-01-05 10:32:21  IP: 218.28.167.*

还有联字,当初很著名的微软NOTEPAD鄙视联通的帖子,大家都忘了吗?


#   zdg 发表于2007-01-05 20:57:06  IP:

如何判断编码有些方法,小侯和我做了些探讨,以下是2篇相关文章:
http://blog.csdn.net/zdg/archive/2005/01/29/272643.aspx
http://blog.csdn.net/houjianxun/archive/2005/02/24/299593.aspx

 来自:http://blog.csdn.net/myan/archive/2007/01/04/1474112.aspx

无觅相关文章插件,快速提升流量