Heim > Backend-Entwicklung > PHP-Tutorial > 由编码识别遇到有关问题,思考utf8编码正则表达式(php版本)

由编码识别遇到有关问题,思考utf8编码正则表达式(php版本)

WBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWB
Freigeben: 2016-06-13 10:47:09
Original
1160 Leute haben es durchsucht

由编码识别遇到问题,思考utf8编码正则表达式(php版本)

?

  • 起因:

最近遇到一件事情,一个接口能够接收传入编码可能是utf-8,gbk 两种。 做过编码方面转换的同学应该知道的,是什么编码不会在字符串里面有什么标记位的。不过utf-8编码有特殊性,因此可以通过正则表达式来检查。只要发现是utf-8编码。就转换,不是utf-8就当gbk处理。 编码一些常见问题可以查看:由web程序出现乱码开始挖掘(Bom头、字符集与乱码)

  • 行动:

知道这个原理,马上领任务,开始工作。 想到php版本有个mbstring模块可以进行编码检测转换:

<span style="line-height: 1.5; color: #0000ff;"></span>php<span style="line-height: 1.5; color: #008000;">//当前编码是gbk</span>$str="<span style="line-height: 1.5; color: #8b0000;">中国</span>";$aStrList=array($str,iconv('<span style="line-height: 1.5; color: #8b0000;">gbk</span>','<span style="line-height: 1.5; color: #8b0000;">utf-8</span>',$str));foreach ($aStrList as $v){	echo mb_convert_encoding($v,'<span style="line-height: 1.5; color: #8b0000;">gbk</span>','<span style="line-height: 1.5; color: #8b0000;">utf-8,gbk</span>'),"<span style="line-height: 1.5; color: #8b0000;">\r\n</span>";}
Nach dem Login kopieren
?
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
运行结果:
Nach dem Login kopieren
<img alt="image"    style="max-width:90%" src="/img/2012/09/13/182309550.png" title="image" style="border-color: initial; display: inline;"  style="max-width:90%"> 
Nach dem Login kopieren
?
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
两个不同编码的“中国”,用一个函数mb_convert_encoding就可以自动转换成gbk编码。首页,尝试用utf-8解码,如果出现问题,就会用gbk转码。看来问题解决了,哈哈,可以交差了……
Nach dem Login kopieren
?
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
  1. 问题:
发布后,平静了几天,突然接到反馈:有中文:”袁小”解码出错。⊙﹏⊙b汗 …… ,想……(难道php内置检测模块有问题,或是我哪里欠缺……)
Nach dem Login kopieren
<img alt="image"    style="max-width:90%" src="/img/2012/09/13/182309551.png" title="image" style="border-color: initial; display: inline;"  style="max-width:90%"> 
Nach dem Login kopieren
⊙﹏⊙b汗……  看来果然有问题,查询手册:<strong>mbstring 模块编码检查,只是识别字符串部分编码,发现与某个字符集匹配上,就认为它属于那种编码。 这不属于它的bug,因为字符串本身没有编码信息标识,没有那个语言能够完全检测通过。 </strong>
Nach dem Login kopieren
<strong></strong>?
Nach dem Login kopieren
Nach dem Login kopieren
  1. 问题:
能不能自己写一个检查正则表达式看下到底怎么样呢?要写正则表达式,首先须了解utf8编码规范,查看:http://zh.wikipedia.org/zh/UTF-8?
Nach dem Login kopieren

image

目前编码集合只有这样6个维度:php得到维度代码

<span style="line-height: 1.5; color: #0000ff;"></span>php<span style="line-height: 1.5; color: #008000;">//得到utf8字编码各个维度的范围 </span>echo base_convert('<span style="line-height: 1.5; color: #8b0000;">1111111</span>',2,16),"<span style="line-height: 1.5; color: #8b0000;">\r\n</span>";<span style="line-height: 1.5; color: #008000;">//维度1</span>echo base_convert('<span style="line-height: 1.5; color: #8b0000;">10000000</span>',2,16),base_convert('<span style="line-height: 1.5; color: #8b0000;">10111111</span>',2,16),"<span style="line-height: 1.5; color: #8b0000;">\r\n</span>";echo base_convert('<span style="line-height: 1.5; color: #8b0000;">11000000</span>',2,16),base_convert('<span style="line-height: 1.5; color: #8b0000;">11011111</span>',2,16),"<span style="line-height: 1.5; color: #8b0000;">\r\n</span>";<span style="line-height: 1.5; color: #008000;">//维度2</span>echo base_convert('<span style="line-height: 1.5; color: #8b0000;">11100000</span>',2,16),base_convert('<span style="line-height: 1.5; color: #8b0000;">11101111</span>',2,16),"<span style="line-height: 1.5; color: #8b0000;">\r\n</span>";<span style="line-height: 1.5; color: #008000;">//维度3</span>echo base_convert('<span style="line-height: 1.5; color: #8b0000;">11110000</span>',2,16),base_convert('<span style="line-height: 1.5; color: #8b0000;">11110111</span>',2,16),"<span style="line-height: 1.5; color: #8b0000;">\r\n</span>";<span style="line-height: 1.5; color: #008000;">//维度4</span>echo base_convert('<span style="line-height: 1.5; color: #8b0000;">11111000</span>',2,16),base_convert('<span style="line-height: 1.5; color: #8b0000;">11111011</span>',2,16),"<span style="line-height: 1.5; color: #8b0000;">\r\n</span>";<span style="line-height: 1.5; color: #008000;">//维度5</span>echo base_convert('<span style="line-height: 1.5; color: #8b0000;">11111100</span>',2,16),base_convert('<span style="line-height: 1.5; color: #8b0000;">11111101</span>',2,16),"<span style="line-height: 1.5; color: #8b0000;">\r\n</span>";<span style="line-height: 1.5; color: #008000;">//维度6</span>
Nach dem Login kopieren

运行结果:

image

  1. 通过上面6个维度得到得到对应的正则表达式:

[\x01-\x7f]|[\xc0-\xdf][\x80-\xbf]|[\xe0-\xef][\x80-\xbf]{2}|[\xf0-\xf7][\x80-\xbf]{3}|[\xf8-\xfb][\x80-\xbf]{4}|[\xfc-\xfd][\x80-\xbf]{5}

以上分别是各个维度范围

<span style="line-height: 1.5; color: #0000ff;"></span>php<span style="line-height: 1.5; color: #008000;">//当前编码是gbk</span>$str="<span style="line-height: 1.5; color: #8b0000;">袁</span>";echo urlencode($str);echo is_utf8($str);function is_utf8($str){	<span style="line-height: 1.5; color: #008000;">///utf8编码正则检测函数</span>	<span style="line-height: 1.5; color: #008000;">///copyright qq:8292669  http://www.cnblogs.com/chengmo</span>	$re='<span style="line-height: 1.5; color: #8b0000;">/^([\x01-\x7f]|[\xc0-\xdf][\x80-\xbf]|[\xe0-\xef][\x80-\xbf]{2}|[\xf0-\xf7][\x80-\xbf]{3}|[\xf8-\xfb][\x80-\xbf]{4}|[\xfc-\xfd][\x80-\xbf]{5})+$/</span>';	return preg_match($re,$str);}
Nach dem Login kopieren
<strong><span style="line-height: 1.5; color: #ff0000;">上面执行结果返回为1,然后”袁“本身应该是gbk编码。看来上面函数还是不能彻底检查utf8编码。分析原因,从上面正则可以看到,utf8的6个维度对应字节长度从1-6字节。 而gbk是1-2个字节。因此他们之间会在1-2个字节长度地方检查出现重合。1个字节的时候gbk与utf8的 编码与字符对应关系都一样,但是2个字节时候,对应编码与字符各不相同。</span></strong>
Nach dem Login kopieren
?
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
通过查询gbk编码表:http://www.knowsky.com/resource/gb2312tbl.htm 进一步确认,范围会在:
Nach dem Login kopieren
[c0-df][a0-bf]  之内汉字都会有问题了。 <strong>如果纯这个范围的汉字组合为字符串就会出现判断不了情况。如果它与其它范围字符组合都可以正确的判断出来。</strong>
Nach dem Login kopieren
<strong></strong>?
Nach dem Login kopieren
Nach dem Login kopieren

GBK与UTF8字符集重叠对应的字符是:(gbk编码表)

?
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren
Nach dem Login kopieren

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage