标签归档:编码

浏览器提交数据编码测试

PHP脚本文件使用GB2312编码
Chrome浏览器能自动检测到是GBK编码,文件中的中文字符(GB2312编码)能正确显示。
1)POST提交中文字符数据,编码是EUC-CN(GB2312),GET提供中文字符串数据(?s=字符编码),检测到提交过来的数据是UTF-8编码,显示也是乱码(因为使用GBK编码解释UTF-8编码的数据)。
2)AJAX POST提交中文字符数据,编码是UTF-8;AJAX GET提供中文字符串数据,编码是EUC-CN(GB2312)

火狐浏览器测试除了AJAX GET提供中文字符串数据,编码是UTF-8外(尽管JS脚本是使用GB2312编码)其它跟chrome一致。

Safari for Windows测试跟chrome一致。

Opera测试跟chrome一致。

IE 8(win 7捆绑),在GET提供中文字符串数据(?s=字符编码),检测到提交过来的数据是EUC-CN(GB2312),这个跟firefox和chrome和Opera都不一样。其它跟chrome一致。

360安全浏览器(基于IE内核),跟chrome一样。

说明:AJAX的POST提交使用JQuery的$.post方法,在查看请求头时,发现:

Content-Type	application/x-www-form-urlencoded; charset=UTF-8

这个字符编码不确定是浏览器添加的还是JQuery添加的,如果是JQuery添加的,那么它还要负责把POST的数据转换成UTF-8编码,所以估计应该是浏览器行为。

从以上比较可以看出,POST提交的数据的编码跟form表单的编码一致,但是GET提交的数据在有中文时一般采用了UTF-8编码,但是IE浏览器视乎不遵守这个规则,高版本的IE估计会遵守规则,不过这个奇葩还是尽量少用或不用。

使用Ajax方法提交数据时,在GET提交数据上,视乎是跟脚本的编码一致的,但是firefox直接无视这个通用规则,它使用UTF-8编码。在POST提交数据上,都一致使用UTF-8编码(没有确认是否是JQuery的行为还是浏览器行为)。

当把脚本改为utf-8编码时,不管是什么方式,提交的数据带中文时都是utf-8编码的,唯独IE例外,IE中(Win 7自带版本),GET和AJAX GET提交的数据都是EUC-CN(GB2312)编码的,360浏览器(IE内核),AJAX GET也是EUC-CN(GB2312)。

最后结论是,珍惜生命,请远离IE。GET提交中文数据,服务端得到数据编码可能不一致,尽管大多数浏览器都使用UTF-8编码(低版本浏览器可能不是)。POST提交的数据时跟form表单编码一致,所以是可控的。AJAX提交数据也有差异性,所以在处理多字节字符时,最好统一使用utf-8编码。

最后附上测试程序:
GB2312编码
UTF-8编码

原创文章,转载务必保留出处。
永久链接:http://blog.ifeeline.com/1168.html

UTF-8编码在PHP中的怪异问题

在ThinkPHP说明文档中 入门->命名规范中有这段话:
“另外有一点非常关键,ThinkPHP默认全部使用UTF-8编码,所以请确保你的程序文件采用UTF-8编码格式保存,并且去掉BOM信息头(去掉BOM头信息有很多方式,不同的编辑器都有设置方法,也可以用工具进行统一检测和处理),否则可能导致很多意想不到的问题。”

它是说用UTF-8编码保存文件需要把BOM信息头去掉。BOM信息头是个什么东西?可以参看:
关于字符编码的基本知识
Windows中的UTF-8与Unicode实验

实际上,UTF-8没有字节序的问题,或者说能自动识别,BOM就是文件开头的几个字节,用来标示文件的编码(大头还是小头),PHP中如果使用UTF-8编码保存文件,需要去掉BOM,否则出现诡异问题:
PHP UTF-8编码问题

这里的head标签是配对的,但是浏览器无法识别,看起来是它们的内部编码有问题,不过这种问题,让人百思不得其解,你一定无法想到这个问题是UTF-8编码携带了BOM导致,不管怎么样,我把包含的用UTF-8编码的文件的BOM去掉,这个诡异问题就得到解决了:
UTF-8编码去掉BOM

PHP中对Unicode编码的支持还是存在一些问题,在使用UTF-8编码时务必把BOM去掉。我花了很多时间跟踪代码才找到这个诡异问题的根源,此为一个经验教训,希望各位看官不要重复这样的过程,很悲剧。

永久链接:http://blog.ifeeline.com/952.html

Windows中的UTF-8与Unicode实验

查看“汉”字的Unicode编码(小尾)是496C,过程:(实际这里是UTF-16的编码,由于它在使用2字节编码的时候跟UCS-2编码一致,所以可以通过这个方式直接查看到它的UCS-2编码)

使用16进制编辑器打开:

小尾: 496C的二进制是0100 1001 0110 1100,如果转换为UTF-8,496C落在000800 – 00D7FF中,使用这个二进制分别套入1110xxxx 10xxxxxx 10xxxxxx格式中(从左到右替代x),得到11100100 10100101 10101100(E4 A5 AC)。
大尾:6C49的二进制0110 1100 0100 1001,如果转换为UTF-8, 6C49落在000800 – 00D7FF中,使用这个二进制分别套入1110xxxx 10xxxxxx 10xxxxxx格式中(从左到右替代x),得到11100110 10110001 10001001(E6 B1 89)。
验证结果[UTF-8编码]:(应该是E6 B1 89 或 E4 A5 AC)

“汉”字的GB编码为BABA,如下:

可以看到所谓的保存为ANSI在当前中文系统下就是GB编码,如果是繁体中文系统下,这个ANSI就是指所谓的BIG5。

在Windows中,文本文件可以保存的编码有:

ANSI:        	无格式定义;
Unicode:       	前两个字节为FFFE;
Unicode big endian: 	前两字节为FEFF; 
UTF-8:        	前两字节为EFBB;

这里保存为ANSI编码的就是使用系统默认编码(内码)来打开的。默认编码随系统不同而不同。

关于UTF-16的疑惑
首先是UTF-16的编码规则:

对于U+10000—U+10FFFF之间的字符,取原来编码减去0x10000之后,换成二进制取后20位,按每10位分别对应填入y和x中。

比如:
0x2A6A5这个编码
0x2A6A5 – 0x10000 = 0x1A6A5 = 0001101001 1010100101 对应入格式:

0x2A6A5 转成UTF-16编码是 0xD869 0xDEA5

接下来新建一个Unicode(大尾文件)

然后在16进制编辑器中打开此文件,再往文件里面输入:
FE FF D8 69 DE A5
保存打开:

这个字据说是笔画数最多的汉字,由四个繁体龙子组成。这里也充分证明了Windows里面所谓的Unicode编码实际是指UTF-16(区分大尾小尾),至于UTF-8编码它叫UTF-8,而UTF-16它不叫UTF-16而叫Unicode实在是让人不解了,难道它认为UTF-16和Unicode等同?

事实上,当前的Unicode码范围是0000 – 10FFFF,超过这个最大值的就可以认为不是Unicode码了,上例中的0x2A6A5小于0x10FFFF,而它对应的UTF-16编码都是大于10FFFF的(使用4字节的情况)。

至此,疑惑已去。

参考:
http://zh.wikipedia.org/wiki/UTF-8
http://zh.wikipedia.org/wiki/UTF-16

原创文章,转载务必保留出处。
永久链接: http://blog.ifeeline.com/228.html