如何自动的检测字符串编码

很多时候,一个字符串,你很难检测它的编码。是理论上就不行,比如一个字符串,你把他当作一个utf8的编码是一个汉字串,把他当成gb2312 还是一个汉字出串,而且在字库里面都存在。所以,我们检查也只能是说,大部分能检测出来。

    我遇到的问题是这样的,百度搜索引擎的中关键字的问题。http://www.baidu.com/s?tn=159sifu_pg&wd=%E8%83%8E%E6%95%99%E9%9F%B3%E4%B9%90%E6%AC%A3%E8%B5%8F  在大多数情况下,百度默认编码是gb2312的,如果是utf8会加一个ie字段。但是比如在好hao123里面搜索的,或者其他地方搜索然后进入百度的,可能默认编码是不一样的。比如上面这搜索如果直接输入浏览器,百度自身也是不能解析的,是乱码。

    既然默认编码是gb2312,而且我统计了一下,90%的情况下都是gb2312,所以,我的检测函数不能出现本来是gb2312的,结果被检测出utf8. 基本思路是:

    1. 把所有的ascii去掉,如果全部都是ascii,那么就是gb2312。

    2. 假设这个字符串是gb2312,用一个正则检查它是否是真的gb2312,如果不是,那么就是utf-8

    3. 然后,用iconv 把字符串转换成utf8,如果转换不成功,那么原来可能不是真正的一个gb2312编码的字符

     (用正则匹配我已经尽量精确,但是,gb2312的编码不是连续的,还是会有空洞),那么最后的编码就是utf-8.

    4. 否则就是gb2312 编码

 加入这样的检查功能后,在1000个关键字里面,就出现了1个乱码,比以前的近100个关键字乱码少了很多。

我的这个gb2312 正则判断的不是汉字,而是编码的所有范围了。汉字的范围要小一点。查询详细的gb2312 编码组成情况,可以看我前面的一篇提取关键字的文章,源代码里面有对

gb2312的详细分类。发布一个纯PHP的中文关键字自动提取工具

5. 如果你要更加精确的进行判断,那么还可以进行分词。因为一个字符串,虽然在gb2312下面是汉字,在utf8上也是汉字,但是,在gb2312上构成一个词汇,在utf8上构成一个词汇的概率很小,所以,这样,可以判断分词后一共多少个词,如果用某种编码分词,不能构成词,那么就可以排除这样的情况。但是,大多数情况下没有必要这样精确。

下面是源代码:代码

function utf8_gb2312($str, $default = 'gb2312')
{
    
$str = preg_replace("/[\x01-\x7F]+/", "", $str);
    
if (empty($str)) return $default;
    
    
$preg =  array(
        
"gb2312" => "/^([\xA1-\xF7][\xA0-\xFE])+$/", //正则判断是否是gb2312
        "utf-8" => "/^[\x{4E00}-\x{9FA5}]+$/u",      //正则判断是否是汉字(utf8编码的条件了),这个范围实际上已经包含了繁体中文字了
    );

    
if ($default == 'gb2312') {
        
$option = 'utf-8';
    } 
else {
        
$option = 'gb2312';
    }

    
if (!preg_match($preg[$default], $str)) {
        
return $option;
    }
    
$str = @iconv($default, $option, $str);
    
    
//不能转成 $option, 说明原来的不是 $default
    if (empty($str)) {
        
return $option;
    }
    return $default;
}

 

 

posted @ 2010-12-20 18:46  暮夏  阅读(8789)  评论(0编辑  收藏  举报