需求:當我們傳輸或者存儲含有中文的字符串到某些地方時可能會出現字符串亂碼或未可知問題的情況,所以在最小改動的情況下解決問題
場景:向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") 方法。