如何自动的检测字符串编码
很多时候,一个字符串,你很难检测它的编码。是理论上就不行,比如一个字符串,你把他当作一个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上构成一个词汇的概率很小,所以,这样,可以判断分词后一共多少个词,如果用某种编码分词,不能构成词,那么就可以排除这样的情况。但是,大多数情况下没有必要这样精确。
下面是源代码:代码
{
$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 ;
}
}