JS——URI编码和解码
需求:当我们传输或者存储含有中文的字符串到某些地方时可能会出现字符串乱码或未可知问题的情况,所以在最小改动的情况下解决问题
场景:向Cookie中存储中文是不建议的
技术:使用JS提供的encodeURIComponent() 函数可把字符串作为 URI 组件进行编码
使用JS提供的decodeURIComponent() 函数可把字符串作为 URI 组件进行解码
两者使用的是UTF-8字符集
实现:
案例如下
<script> var afterEncode = encodeURIComponent("中国,五千年文化古国!"); console.log(afterEncode); var afterDecode = decodeURIComponent(afterEncode); console.log(afterDecode); </script>
运行结果
技术说明:
以下内容摘自:CSDN
encodeURI 、encodeURIComponent 以及中文乱码问题
关于前端:
encodeURIComponent(), 对文本框的输入值进行编码,特殊字符编码结果是%加上这些符号的ASCII码十六进制对照表。
encodeURI() 将整个url编码,但不会对如下字符进行编码 @#$&=.:/;?+ ,这些符号的基本上就是http URL中的特殊符号,是不进行编码的。
@ | |
# | 网页中的一个位置 |
:/.?=& | 大多数URL基本都包含了的符号 http://www.a.com/a?a=b&c=d |
; | |
+ | |
$ |
两种方式的关系及区别:
- 无论上述哪一种,都不会对[a-zA-Z0-9]的字符以及 ! * ( ) '. 进行编码,即编码之后还是本身。
- 这两种编码方式对中文的编码结果是一致的。
- encodeURL()不会进行编码的字符,基本都是httpURL中的预留符号。所以,encodeURIComponent()是一定会去对这些符号进行编码的,以免对URL造成干扰。
一些常用的编码结果: (底色部分是encodeURL不编码的字符)
原值 | encodeURIComponent |
encodeURI |
---|---|---|
% | %25 | %25 |
空格 | %20 |
%20 |
& | %26 | & |
= | %3D | = |
/ | %2F | / |
@ | %40 | @ |
; | %3B | ; |
$ | %24 | $ |
: | %3A | : |
+ | %2B | + |
? | %3F | ? |
# | %23 | # |
中文 | %E4%B8%AD%E6%96%87 | %E4%B8%AD%E6%96%87 |
关于后端:
前端传值有2种方式,GET和POST。
一 、POST方式传值中文不会产生乱码问题
- JSP 页面有pageEncoding="UTF-8",进行编码设置;
- web.xml中的 filter 会进行字符编码设置,进行request.setCharacterEncoding("utf-8")操作。
二、GET方式
1. 乱码的产生和解决
大多数的中文乱码是通过GET方式产生的,只因GET方式有自动解码操作。相当于执行代码:
URLDecoder.decode("%E6%B1%89%E5%AD%97", "编码方式")
tomcat的配置文件server.xml中,如果不配置解码方式,就会按照默认的ISO-8859-1编码进行解码。具体参照tomcat的文档。
URIEncoding:This specifies the character encoding used to decode the URI bytes, after %xx decoding the URL. If not specified, ISO-8859-1 will be used.
即服务端就会默认执行 URLDecoder.decode("%E6%B1%89%E5%AD%97", "ISO-8859-1"),即UTF-8编码,ISO解码,就会出现乱码。其中,%E6%B1%89%E5%AD%97 是前端 encodeURI("汉字") 的结果,此函数使用UTF-8编码。
<Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443" />
所以,应该在这里增加 URIEncoding="UTF-8" 的配置,避免乱码。
2.乱码时的问号?
前端处理汉字时用的encodeURI是按照UTF-8方式进行编码,而此种编码方式是一个汉字占3字节。
而通过request取到的参数默认是通过ISO-8859-1的方式进行解码,找到就显示?了,并且是3倍于汉字的个数。
3.通过两次 encodeURI 也可以解决乱码问题
a . 将“汉字”通过encodeURI或者 encodeURIComponent 编码一次,会得到字符串 %E6%B1%89%E5%AD%97(6字节),此字符串使用UTF-8编码的,如果此时用ISO-8859-1解码,在ISO-8859-1的编码表中找不到“E6”等字段对应的字符,所以是6个问号。
b . 第二次编码时,相当于对非中文字符 %E6%B1%89%E5%AD%97 进行编码,此时服务端无论用哪种解码方式,都将得到 %E6%B1%89%E5%AD%97 字符,可以正确还原 。
c . 这样,再通过UTF-8 解码该字符,就可以得到“汉字”了。
即执行 URLDecoder.decode("%E6%B1%89%E5%AD%97", "UTF-8") 方法。