声明:以下内容仅为个人理解,但不保证百分百正确,请观者慎重甄辨。
在web开发过程中很容易遇到编码问题,表现形式就是各种的乱码,它们存在的原因有可能因为数据库表的编码与处理程序没有一致,有可能是程序文件本身的编码没有规范,也有可能仅仅是因为<meta>标签指定解析的编码方式与文件编码有出入。更多的情况希望在评论中给出,为减少别人误区而写博客。
出现乱码最多的原因当然是因为页面中有汉字,处理汉字的问题成了我这样人的痛。
以下关键字,Unicode编码,utf-8,utf-16,utf-32,GBK,gb2312,Big5,UCS-2, UCS-4,ISO 10646等等内容如需更深学习请见百度百科,我简单介绍下这些关键字。
Unicode组织和utf-8,utf-16,utf-32有关,GBK跟gb2312,Big5有关,跟国际标准组织有关的是
UCS-2, UCS-4,ISO 10646。
utf-8以字节为单位的,范围在1-6个字节的变字节的编码方案,utf-16以16位无符号数为单位,utf-32以32位无符号数为单位。
GBK编码是双字节编码,完全兼容gb2312,并包括了Big5编码中所有的汉字,是gb2312-80基础上的扩展。
汉字,或者是简体中文的范围是我们最常处理的问题。
以下是我在学习过程中犯得错误,在gb2312中简体中文的范围是B0A1-F7FE(http://tool.xker.com/gb2312tbl.php)。
B0A1很容易就转换为二进制 1011 0000 1010 0001
也很容易转换为十进制数 176 161
同理F7FE转换为 1111 0111 1111 1110
十进制为 247 254
然后我想当然的把正则表达式写成这样:
/^[chr(176).chr(161)-chr(247).chr(254)]+$/ 或者
这样写的代价是把很多字都丢掉了。例如“包”、“国”之类。
而正确的写法确实下面的写法:
/^( [chr(176) - chr(247) ] [ chr(161) - chr(254)] )+$/
在utf8下,是如何转换的呢?所以人都知道utf8编码的范围是一个字节到六个字节,一个汉字会占3个字节。这个“3”会在下面起到一定的作用。
在utf8中我们不说简体中文了,因为在utf8中是以汉字的笔画排序,没有简体中文的范围一说。而汉字的范围是4E00-9FA5,我的验证是4E00-9FAF。
他们之间是怎样转换的呢?
Utf8三个字节的固定 模板 是 1110xxxx 10xxxxxx 10xxxxxx
4E00 + 模板 = E4B880
在php中,utf8编码的汉字的匹配范围可以分开三个字节写。
正则表达式如下:
/^([".chr(0xe4)."-".chr(0xe9)."][".chr(0x80)."-".chr(0xbf)."][".chr(0x80)."-".chr(0xbf)."])+$/
但一般都是按一个整体写,如下:
/^[\x{4e00}-\x{9faf}]+$/u
u代表的是字符修正符,类似的Js里gb2312编码的正则表达式写法如下:
/^[\u4e00-\u9fa5]+$/.test(“攻城狮”);
好了,关于编码的问题我们先写到这里。如有补充,以后再说!