1,瞭解爲何java內存編碼用utf-16,網絡傳輸用utf-8javascript
2,java web的編碼問題
URL httpHeader POST表單 HttpBody
JS編碼
其餘編碼
3,常見問題分析
中文編程看不懂字符
一個漢字變成一個問號
一個漢字變成兩個問號
1、爲何要編碼?
計算機儲存信息的最小單元是1個字節,能表示的字符範圍是0-255
咱們要表示的字符號太多,1個字節遠遠不夠,所以要有一個新的類型char,從char到byte必須編碼。
2、常見編碼格式有哪些?
1,ASCII碼
用一個字節的低7位表示,00-7F(即0-127)範圍,0-31是回車、換行、刪除等控制字符,32-126是打印字符,能夠用鍵盤輸入並顯示出來。
2,ISO-8856-1
ASCII碼共128個字符是遠遠不夠的,ISO組織又制定了這個標準。以單字節表示,共256個字符。對於英文字符是足夠了。
3,GB2312
中文全稱爲 「信息交換用漢字編碼字符集」 ,雙字節的。GB2312 共收錄有 7445 個字符,其中簡化漢字 6763 個,字母和符號 682 個
4,GBK
全稱「漢字內碼擴展規範」,爲了擴展GB2312,故兼容GB2312,能表示21003個漢字。
5,GB18030
是我國強制標準,但實際應用系統並很少。
6,UTF-16
Unicode,是ISO視圖建立一個全新的超語言字典,能夠互相翻譯全世界全部語言。UTF-16定義了Unicode在計算機的存取方法,用兩個字節表示Unicode的轉化格式,兩個字節是16位,故叫UTF-16。UTF-16表示字符很方便,簡化了字符串操做,
所以Java以UTF-16做爲內存的字符存儲格式。
7,UTF-8
UTF-16統一用量個字節表示一個字符,雖然表示很簡單方便,但缺點是很大一部分字符能夠用一個字節表示,缺佔了兩個字節,存儲空間上放大了一倍。在網絡帶寬有限的狀況下,增大網絡流量。UTF-8採用變長技術,不一樣類型的字符能夠由1-6個字節組成。
故網絡編碼多用UTF-8
編碼格式對比,GB2312與GBK,GBK範圍更大,選GBK。
UTF-8與UTF-16,UTF-16的編碼效果高,轉換簡單,適合在內存和磁盤中操做,JAVA內存編碼就是UTF-16。
對於網絡傳輸,容易損壞字節流,加上傳輸量因素,選擇UTF-8更好。編碼效率而言,GBK<UTF-8<UTF-16,故中文編碼的網絡傳輸採用UTF-8最理想。
3、JAVA中要編碼的場景
1,磁盤IO操做
文件讀寫類,FileOutputStream和FileInputStream,只要統一設置編解碼字符集,通常不會出現亂碼問題。要注意的是有些應用程序不指定編碼格式,中文環境中會用操做系統默認編程,換成其餘操做系統環境可能會出問題。強烈建議指定編碼格式。
2,內存操做中
String和byte[]的互相轉換,設置統一編解碼格式也不會出現問題。
3,Java Web中的編碼,這個問題是重中之重
從使用中文角度來講,有IO的地方就有編碼。網絡傳輸中是以字節爲單位的,全部數據都要能被序列化成字節。
(1)URL編碼
從瀏覽器發情一次HTTP請求,存在編碼的地方是URL、Cookie、Paramiter
完整URL:http://localhost:8080/oa/base/userServlet/張三.do?name=張三
Domain:localhost
port:8080
ContextPath:oa
ServletPath:base/userServlet
PathInfo:張三.do
QueryString:name=張三
URI部分:oa/base/userServlet/張三.do
以谷歌瀏覽器爲例,F12打開調試,能夠看到是UTF-8編碼的。
chrome下不管請求地址和參數,均通過utf-8編碼;但其餘瀏覽器不必定是這樣,好比IE是GBK編碼。
如360瀏覽器,請求地址是這樣,PathInfo是GBK編碼,QueryString是utf-8編碼.可能你的結果不一樣,可是PathInfo和QueryString編碼不一樣是存在的。
http%3A%2F%2Flocalhost%3A8080%2Foa%2Fbase%2FuserServlet%2F
%D5%C5%C8%FD%2Edo%3Fname%3D
%25E5%25BC%25A0%25E4%25B8%2589
編碼和解碼不是程序中能徹底控制的,因此要儘可能避免在URL中使用非ASCII字符。最好在服務端設置。以tomcat爲例
在tomcat的server.xml下的connetor屬性中增長URIEncoding或者useBodyEncodingForURI屬性,若是不設置則tomcat按默認ISO-8856-1來解碼。
(2)HTTP Header編碼
瀏覽器發起 http請求,Header中cookie等參數也存在編碼問題。tomcat從byte到char轉化一樣默認是ISO-8856-1。
(3)POST表單的編解碼
在頁面點提交按鈕時,先根據ContentType對錶單填寫項編碼,在服務端一樣用這個編碼來解碼,通常不會有問題。這個編碼個是咱們程序能夠控制的,如rquset.setCharacterEncoding(charset)。若是不設置,
按系統默認編碼來解析。包括上傳文件也是字節流。
(4)HTTP BODY
這些內容經過Response返回給客戶端瀏覽器。也是先通過編碼,再到瀏覽器解碼。能夠經過response.setCharacterEncoding(charset)設置,瀏覽器客戶端根據html中的 <meta http-equiv=content-type content="text/html; charset=utf-8">來解碼
4,Js中的編碼
若是外部js文件與當前頁面編碼不一致,可能會出現編碼問題。因此統一引入 js文件時加編碼
<
script
type
=
"text/javascript"
src
=
"resource/js/ueditor/ueditor.config.js"
charset
=
"utf-8"
></
script
>
js發起一步調用的URL也受瀏覽器影響,也要encodeURI()這樣的函數來UTF-8編碼,完全解決編碼問題
5,Js編碼,後臺java解碼
天然所有UTF-8
6,其餘
開發環境IDE,設置文件的編碼格式。 xml 設置, jsp contentType="text/html; charset=UTF-8"
4、常見問題分析
1,一個漢字變成兩個亂碼字符
字節數沒丟,說明編碼沒錯多是GBK,解碼用了ISO-8856-1。
2,每一個漢字變成一個問號
如:"天氣很好" 變成 "? ? ? ?"。編碼時字節丟失,使用了ISO-8856-1,碼值爲3F,ISO-8856-1解碼時都變成3F對應的?號
3,一個漢字變成兩個問號
如:"天氣很好" 變成 "? ? ? ? ? ? ? ?"這種比較複雜,中文通過屢次編碼,有一次編碼或解碼使用了ISO-8856-1。要每一個編解碼環節仔細查看。
4,國際化問題
首先要用支持多語言的UTF-8編碼,又一個使用UTF-8的必要性。國際化有springi18見其餘相關文章。