Ajax[转]URL汉字编码问题(及乱码解决)

本文转自:

http://blog.csdn.net/sdtsfhh/article/details/8147243

 

转载声明:本文转载自:leowzy(http://leowzy.iteye.com/blog/794464)。

一如既往、问题之来由

URL就是网址,只要上网,就得会为此到。

Ajax 1

相似的话,URL只能使用英文字母、阿拉伯数字与一些标点符号,不可知运用其他文字和记。比如,世界上出英文字母的网址
“http://www.abc.com”,但是没有希腊字母的网址“http://www.aβγ.com”(读作阿尔法-贝塔-伽玛.com)。这是因为网络标准[RFC
1738](http://www.ietf.org/rfc/rfc1738.txt) 做了硬性规定:

“…Only alphanumerics [0-9a-zA-Z],
the special characters “$-_.+!*'(),” [not including the quotes –
ed], and reserved characters used for their reserved purposes may be
used unencoded within a URL.”

style=”font-size: 12px;”>“只发生字母和数字[0-9a-zA-Z]、一些特殊符号“$-_.+!*'(),”[无包对引号]、以及某些保留字,才得免经编码直接用于
URL。”

随即代表,如果URL中发生汉字,就得编码后使。但是麻烦的是,RFC
1738尚无规定实际的编码方法,而是交由应用程序(浏览器)自己控制。这导致“URL编码”成为了一个无规律的圈子。

下就是被咱省,“URL编码”到底有多杂乱。我会依次分析四种植不同之图景,在各个一样种植状态遇,浏览器的URL编码方法都未均等。把它的差别解释清楚以后,我再说什么用Javascript找到一个合的编码方法。

老二、情况1:网址路径中寓汉字

开拓IE(我因此底凡8.0本),输入网址“http://zh.wikipedia.org/wiki/春节
”。注意,“春节”这简单只字此时是网址路径的相同有的。

Ajax 2

查看HTTP请求的头信息,会意识IE实际查询的网址是“http://zh.wikipedia.org/wiki/%E6%98%A5%E8%8A%82
”。也就是说,IE自动将“春节”编码成了“%E6%98%A5%E8%8A%82”。

Ajax 3

咱俩知晓,“春”和“节”的utf-8编码分别是“E6
98 A5”和“E8 8A
82”,因此,“%E6%98%A5%E8%8A%82”就是随顺序,在每个字节前加上%而取的。(具体的转码方法,请参考我写的《字符编码笔记》 。)

当Firefox中测试,也取得了相同的结果。所以,敲定1就算是,网址路径的编码,用的是utf-8编码。

老三、情况2:查询字符串包含汉字

每当IE中输入网址“http://www.baidu.com/s?wd=春节
”。注意,“春节”这片只字此时属查询字符串,不属网址路径,不要与气象1歪曲。

Ajax 4

查阅HTTP请求的腔信息,会发现IE将“春节”转化成为了一个乱码。

Ajax 5

切换到十六进制方式,才会清楚地观望,“春节”被改变成为了“B4
BA BD DA”。

Ajax 6

咱俩知晓,“春”和“节”的GB2312编码(我之操作系统“Windows
XP”中文版的默认编码)分别是“B4 BA”和“BD
DA”。因此,IE实际上就是是用查询字符串,以GB2312编码的格式发送出。

Firefox的处理方式,略有不同。它发送的HTTP
Head是“wd=%B4%BA%BD%DA”。也就是说,同样用GB2312编码,但是当每个字节前增长了%。

Ajax 7

所以,敲定2即使是,查询字符串的编码,用之是操作系统的默认编码。

季、情况3:Get方法变的URL包含汉字

前说的凡直接输入网址的事态,但是又广泛的状况是,在已经开辟的网页上,直接用Get或Post方法有HTTP请求。

据悉台湾中兴大学吕瑞麟先生的考
,这时的编码方法由网页的编码决定,也便是由于HTML源码中字符集的设定控制。

  <meta http-equiv=”Content-Type”
content=”text/html;charset=xxxx”>

倘点立同履行最终的charset是UTF-8,则URL就以UTF-8编码;如果是GB2312,URL就盖GB2312编码。

举例来说,百度是GB2312编码,Google是UTF-8编码。因此,从它的搜寻框中找寻与一个乐章“春节”,生成的查询字符串是勿一致的。

百度生成的凡%B4%BA%BD%DA,这是GB2312编码。

Ajax 8

Google生成的凡%E6%98%A5%E8%8A%82,这是UTF-8编码。

Ajax 9

所以,结论3就是,GET和POST方法的编码,用之凡网页的编码。

五、情况4:Ajax调用的URL包含汉字

眼前三种植状态还是由浏览器发出HTTP请求,最后一种植情景则是由Javascript生成HTTP请求,也不怕是Ajax调用。还是根据吕瑞麟先生的章,在这种状况下,IE和Firefox的处理方式完全无等同。

比喻来说,有如此少尽代码:

  url = url + “?q=”
+document.myform.elements[0].value; //
假定用户以表单中付出的值是“春节”这片只字

  http_request.open(‘GET’, url,
true);

这就是说,无论网页使用啊字符集,IE传送给服务器的连天“q=%B4%BA%BD%DA”,而Firefox传送给服务器的连“q=%E6%98
%A5%E8%8A%82”。也就是说,以Ajax调用中,IE总是以GB2312编码(操作系统的默认编码),而Firefox总是采取utf-8编码。这就算是我们的结论4。

六、Javascript函数:escape()

吓了,到此结束,四栽状态尚且说罢了。

倘前面你都看明白了,那么这公应有会感觉特别讨厌。因为,实在太拉杂了。不同的操作系统、不同的浏览器、不同之网页字符集,将促成全盘不同的编码结果。如果程序员要将各级一样种结果都考虑进来,是匪是极度恐怖了?有没有发出方法,能够确保客户端只所以同一栽编码方法向服务器发出请求?

对是局部,就是使Javascript先对URL编码,然后再次于服务器交由,不要给浏览器与的火候。因为Javascript的输出总是一样的,所以就是保证了服务器得到的数是格式统一的。

Javascript语言用于编码的函数,一共来三独,最古老的一个纵是escape()。虽然是函数现在都不提倡使用了,但是由于历史由来,很多地方还当以其,所以来必不可少先从它张嘴起。

事实上,escape()不能够直接用于URL编码,它的实在作用是回到一个字符的Unicode编码值。比如“春节”的归来结果是%u6625%u8282,也就是说在Unicode字符集中,“春”是第6625单(十六进制)字符,“节”是第8282只(十六进制)字符。

Ajax 10

其的现实规则是,除了ASCII字母、数字、标点符号“@
* _ + – .
/”以外,对其它有字符进行编码。在\u0000到\u00ff之间的标记为转成%xx的款式,其余符号被转成%uxxxx的款式。对应之解码函数是
unescape()。

故而,“Hello
World”的escape()编码就是“Hello%20World”。因为空格的Unicode值是20(十六进制)。

Ajax 11

再有一定量独地方用小心。

首先,无论网页的原始编码是啊,一旦被Javascript编码,就还变为unicode字符。也就是说,Javascipt函数的输入和出口,默认都是Unicode字符。这等同碰对下两单函数也适用。

Ajax 12

下,escape()不对“+”编码。但是咱领略,网页在交表单的时,如果出空格,则会受转正为+字符。服务器处理数量的下,会把+号处理成空格。所以,使用的时候如果小心。

七、Javascript函数:encodeURI()

encodeURI()是Javascript中确用来针对URL编码的函数。

其相于对整URL进行编码,因此除常见的记号以外,对其余部分于网址中发生异常含义的符号“;
/ ? : @ & = + $ ,
#”,也不进行编码。编码后,它输出符号的utf-8形式,并且于每个字节前加上%。

Ajax 13

其对应之解码函数是decodeURI()。

Ajax 14

欲注意的是,它不对准单引号’编码。

八、Javascript函数:encodeURIComponent()

最后一个Javascript编码函数是encodeURIComponent()。与encodeURI()的分别是,它用于对URL的一对进行独家编码,而休用于对普URL进行编码。

因此,“; / ? : @ & = + $ ,
#”,这些当encodeURI()中未让编码的标记,在encodeURIComponent()中皆会吃编码。至于实际的编码方法,两者是千篇一律。

Ajax 15

其对应的解码函数是decodeURIComponent()。

PS1

网页里的form编码其实不了在网页编码,form标记中出一个accept-charset属性,在非ie浏览器种,如果用那赋值(比如
accept-charset=”UTF-8″),则表单会按照这价表示的编码方式进行付出。
在ie下,我的匹配解决办法是: form1.onsubmit=function(){
document.charset=this.getAttribute(‘accept-charset’); }

PS2 :字符编码笔记:ASCII,Unicode和
UTF-8

1. ASCII码

咱们懂得,在微机中,所有的音讯最终都意味为一个二进制的字符串。每一个二进制位(bit)有0和1片种状态,因此八独二进制位就得整合出
256栽状态,这给称作一个字节(byte)。也就是说,一个字节一共可以据此来代表256种不同的状态,每一个态对应一个标记,就是256单记号,从
0000000到11111111。

上个世纪60年代,美国制订了平等法字符编码,对英语字符与二进制位之间的干,做了合确定。这给称作ASCII码,一直沿用至今。

ASCII码一共规定了128个字符的编码,比如空格“SPACE”是32(二进制00100000),大写的字母A是65(二进制
01000001)。这128独记(包括32独无克打印出来的主宰符号),只占了一个字节的末尾7各项,最前方的1位统一规定为0。

2、非ASCII编码

英语用128独记编码就足足了,但是之所以来代表其余语言,128单记号是不够的。比如,在法语中,字母上方有注音符号,它就无法用ASCII码表示。于是,一些欧洲国度就是决定,利用字节中压的万丈位编入新的符号。比如,法语中的é的编码为130(二进制10000010)。这样一来,这些欧洲国度以的编码体系,可以象征极度多256只标志。

而,这里还要出现了初的问题。不同的国家有两样之假名,因此,哪怕它都利用256独记的编码方式,代表的假名却休均等。比如,130在法语编码中意味了é,在希伯来语编码中可意味着了字母Gimel
(ג),在俄语编码中同时会代表任何一个记。但是无论如何,所有这些编码方式中,0—127意味着的符是同等的,不平等的仅仅是128—255之即无异于段子。

至于亚洲国家之契,使用的标记就再次多了,汉字就是大多上10万左右。一个字节只能表示256种植标志,肯定是不够的,就必以多单字节表达一个标记。比如,简体中文常见的编码方式是GB2312,使用有限独字节表示一个中国字,所以理论及最为多足代表256×256=65536单记号。

中文编码的题材待专文讨论,这首笔记不涉及。这里仅仅指出,虽然都是故几近只字节表示一个标记,但是GB类的汉字编码与后文的Unicode和
UTF-8是毫无关系的。

3.Unicode

正要使齐同节省所说,世界上在在冒尖编码方式,同一个二进制数字可以叫诠释成不同的记。因此,要想打开一个文本文件,就务须理解她的编码方式,否则用错误的编码方式解读,就见面并发乱码。为什么电子邮件时出现乱码?就是以发信人和收信人使用的编码方式不相同。

得想像,如果有雷同栽编码,将世界上具有的记都纳入其中。每一个符号都与一个举世无双之编码,那么乱码问题不怕见面磨。这即是Unicode,就像它的名字都意味着的,这是一致种具有符号的编码。

Unicode当然是一个非常特别之集聚,现在之规模得以容纳100差不多万个号。每个符号的编码还不等同,比如,U+0639意味着阿拉伯字母
Ain,U+0041意味着英语的不胜写字母A,U+4E25表示汉字“严”。具体的号对应表,可以查询unicode.org  ,或者特别的字对应表 。

4. Unicode的问题

待专注的是,Unicode只是一个标记集,它只确定了标记的次向前制代码,却从没规定之二进制代码应该如何存储。

随,汉字“严”的unicode是十六进制数4E25,转换成为二向前制数足足有15位(100111000100101),也就是说这个符号的象征至少要2个字节。表示其余还怪的记号,可能需要3单字节或者4只字节,甚至又多。

此地虽发出一定量个严重的题材,第一单问题是,如何才能够分unicode和ascii?计算机怎么知道老三独字节表示一个记,而未是独家代表三个号为?第二单问题是,我们就掌握,英文字母只所以一个字节表示即够用了,如果unicode统一确定,每个符号用三个或四单字节表示,那么每个英文字母前都必将产生次及三只字节是0,这对于仓储来说是特大的浪费,文本文件的高低会用大出二三倍,这是无力回天接受的。

它造成的结果是:1)出现了unicode的强存储方,也就是说有许多种不同的第二向前制格式,可以用来代表unicode。2)unicode
在十分丰富一段时间内无法放开,直到互联网的面世。

5.UTF-8

互联网的推广,强烈要求出现雷同种统一的编码方式。UTF-8就是以互联网及采取最广的一样种植unicode的兑现方式。其他实现方式尚包UTF-
16以及UTF-32,不过以互联网及着力不用。还雷同整个,这里的涉嫌是,UTF-8是Unicode的兑现方式有。

UTF-8最老之一个特性,就是它是如出一辙种植变长的编码方式。它可以使1~4独字节表示一个号,根据不同之标记而变化字节长度。

UTF-8的编码规则不行简短,只来第二漫漫:

1)对于单字节的记号,字节的率先各项而为0,后面7各呢这个符号的unicode码。因此于英语字母,UTF-8编码和ASCII码是平之。

2)对于n字节之记(n>1),第一独字节的面前n位都使为1,第n+1位设为0,后面字节的前片个一律要为10。剩下的无提及的二进制位,全部吧之标记的unicode码。

下表总结了编码规则,字母x表示可用编码的号。

Unicode符号范围 | UTF-8编码方式
(十六进制) | (二进制)
——————–+———————————————
0000 0000-0000 007F | 0xxxxxxx 0000 0080-0000 07FF | 110xxxxx 10xxxxxx
0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx 0001 0000-0010 FFFF |
11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

下面,还是以汉字“严”为例,演示如何促成UTF-8编码。

早就清楚“严”的unicode是4E25(100111000100101),根据上表,可以发现4E25远在第三实行之克外(0000
0800-0000 FFFF),因此“严”的UTF-8编码需要三单字节,即格式是“1110xxxx
10xxxxxx
10xxxxxx”。然后,从“严”的终极一个二进制位开始,依次从晚迈入填入格式中的x,多发生的号补0。这样即便得到了,“严”的UTF-8编码是
“11100100 10111000 10100101”,转换成十六进制就是E4B8A5。

6. Unicode和UTF-8之间的变换

经上亦然省之例子,可以见到“严”的Unicode码是4E25,UTF-8编码是E4B8A5,两者是休雷同的。它们中间的转移可以经过程序实现。

每当Windows平台下,有一个太简便易行的转速方法,就是采取内置的记事本小程序Notepad.exe。打开文件后,点击“文件”菜单中之“另存也”命令,会跳出一个会话框,在最好底部有一个“编码”的下拉条。

Ajax 16

里有四只挑选:ANSI,Unicode,Unicode
big endian 和 UTF-8。

1)ANSI是默认的编码方式。对于英文文件是ASCII编码,对于简体中文文件是GB2312编码(只对Windows简体中文版,如果是繁体中文版会采用Big5码)。

2)Unicode编码指的凡UCS-2编码方式,即直接用简单只字节存入字符的Unicode码。这个选项用的little
endian格式。

3)Unicode big
endian编码与齐一个拣相呼应。我在产同样节约会分解little endian和big
endian的涵义。

4)UTF-8编码,也不怕是高达一样节省谈到的编码方法。

挑收”编码方式“后,点击”保存“按钮,文件的编码方式就即转换好了。

7. Little endian和Big endian

上一节都涉嫌,Unicode码可以用UCS-2格式直接存储。以汉字”严“为条例,Unicode码是4E25,需要因此有限只字节存储,一个字节是4E,另一个字节是25。存储的早晚,4E以面前,25以继,就是Big
endian方式;25每当前,4E于后,就是Little endian方式。

眼看点儿只奇特的名称来英国作家斯威夫就的《格列佛游记》。在该书中,小人国里爆发了内战,战争起因是众人争论,吃鸡蛋时究竟是于大洋(Big-
Endian)敲起要于小头(Little-Endian)敲起。为了及时起工作,前后爆发了六不善乱,一个君主送了命,另一个天王丢了王位。

于是,第一单字节在前面,就是”大头方式“(Big
endian),第二独字节在前边就是是”小头方式“(Little endian)。

这就是说好自然之,就见面产出一个题目:计算机怎么懂得某一个文本到底下哪一样栽方式编码?

Unicode规范着定义,每一个文件之无比前面分别在一个象征编码顺序的字符,这个字符的讳称为”零开间非换行空格“(ZERO
WIDTH NO-BREAK
SPACE),用FEFF表示。这刚是简单个字节,而且FF比FE大1。

万一一个文件文件之峰半独字节是FE
FF,就代表该公文采用大头方式;如果头半单字节是FF
FE,就表示该公文采用小头方式。

8. 实例

脚,举一个实例。

开拓”记事本“程序Notepad.exe,新建一个文书文件,内容就是一个”严“字,依次使用ANSI,Unicode,Unicode
big endian 和 UTF-8编码方式保存。

接下来,用文本编辑软件UltraEdit中
的”十六进制功能“,观察该公文之内编码方式。

1)ANSI:文件的编码就是少单字节“D1
CF”,这正是“严”的GB2312编码,这也暗示GB2312是行使大头方式囤的。

2)Unicode:编码是四只字节“FF FE 25
4E”,其中“FF FE”表明是小头方式囤,真正的编码是4E25。

3)Unicode big endian:编码是四只字节“FE
FF 4E 25”,其中“FE FF”表明是大头方式囤。

4)UTF-8:编码是六独字节“EF BB BF E4 B8
A5”,前三个字节“EF BB
BF”表示马上是UTF-8编码,后三单“E4B8A5”就是“严”的有血有肉编码,它的积存顺序和编码顺序是均等的。

9. 拉开阅读

* The
Absolute Minimum Every Software Developer Absolutely, Positively Must
Know About Unicode and Character
Sets  (关于字符集的绝基本知识)

* 谈谈Unicode编码

* RFC3629:UTF- 8, a transformation format of ISO
10646 (如果实现UTF-8的规定)

相关文章