天天看點

JavaWeb技術内幕三:JavaWeb中文編碼問題幾種常見的編碼格式Java中需要編碼的場景Java中如何編解碼Java Web中設計的編解碼在JS中的編碼問題常見問題分析

Java作為跨平台語言,涉及到的編解碼問題也比較多,我們來探讨一下HTTP請求如何控制編碼格式。

幾種常見的編碼格式

為什麼要編碼

由于計算機隻能看懂01,人類隻能看懂字元,是以要進行編碼和解碼。

1 在計算機中,一個位元組是最小的資訊存儲單元,而一個位元組隻能表示256個字元。

2 人類需要的符号遠遠超過256個。

如何翻譯

各種語言需要交流,如何進行翻譯呢,在計算機中提供了常見的翻譯方式。比如ASCII,UTF-8等編碼方式,他們可以被看做字典,可以讓位元組數組變成對應的字元。那麼他們有什麼差別呢。

1 ASCII碼

一共有128個,用一個位元組的低七位表示。

2 ISO

128個字元顯然不夠用,于是在ASCII基礎上建立了ISO-8559編碼。雖然仍是單位元組,但可以表示256字元。

3 GB2312

是雙位元組編碼,可以表示6763個漢字

4 GBK

它擴充了GB2312,功能表示21003個漢字。他和GB2312互相相容

5 UTF-16

首先說下Unicode,ISO試圖履歷一個超語言詞典,讓所有語言都可以通過這個字典翻譯。這是非常複雜的。

UTF-16定義了Unicode字元在計算機中的存儲方法,UTF-16用兩個位元組來表示Unicode的轉化格式,并且使用定長的方法,無論什麼字元都可以用2個位元組表示。

這大大簡化了字元串操作,是以Java使用UTF-16作為記憶體字元的存儲格式。

6 UTF-8

UTF-16統一使用兩個位元組表示一個字元,雖然很簡單,但是很多字元隻需要一個位元組就可以表示了,相當于多處用了一倍的空間。

在網絡帶寬有限的情況下,沒有必要。UTF-8使用變長技術,每個編碼區有不同的字碼長度。所有字元可以用1-6個位元組組成。

如果是一個位元組的字元那麼就是ASCII碼了

Java中需要編碼的場景

io操作中存在的編碼

位元組流到字元流的互相轉換需要用到編碼

記憶體操作中的編碼

使用String字元串和byte數組進行互相轉換時,需要指定編碼

Java中如何編解碼

一般指定charsetname為指定編碼格式即可。

各種編碼實踐

對幾種編碼格式的比較

1 對于中文字元,使用GBK好一點

2 對于Unicode字元,使用UTF-16的編碼效率較高,轉換更簡單,進行字元串操作也更好,适合在磁盤和記憶體之間使用,但是不适合進行網絡傳輸,因為雙位元組容易損壞,且占用空間大。

3 UTF-8更适合網絡傳輸,UTF-8使用單位元組存儲,單個字元損壞不影響其他字元。

Java Web中設計的編解碼

對于http網絡傳輸,考慮壓縮資料,減少網絡傳輸量,但是有的壓縮算法隻減少字元數但是不減少位元組數。

在計算機中,漢字的表示方式一般是一個字元使用兩個位元組來表示,是以Java的char類型也是16個bit,也就是2個位元組。

JavaWeb可能出現編碼轉換的地方:

1 HTTP請求中的URI,Cookie,Post表單參數需要解碼。

2 資料庫的讀寫,檔案讀寫需要編解碼。

3 所有資料從socket傳回時需要編碼,浏覽器解析頁面需要解碼。

URL的編解碼

一個URL可以被分為好多個組成部分

http://localhost:8080/hello/servlet/黃蓬龍?name=h2pl

scheme domain port context servletpath pathinfo querystring

這部分中,url不包括querystring,uri則隻包括hello/servlet/黃蓬龍,也就是context+servletpath+pathinfo。

是以uri隻是定位資源,但是不包括網絡協定

對于Tomcat而言,servlet會把這個url解析為一下幾個部分。

事實上一部配置設定置是在server.xml配置檔案中定義的。

1 port是配置檔案中的connector port定義的。

2 context path是在配置檔案中定義的

3 servletpath是web.xml的url-pattern中定義的。

4 pathinfo是我們具體請求的servlet

5 querystring是要傳遞的參數
           

pathinfo采用utf-8編碼,querystring采用gbk編碼

總結就是,url的編解碼過程比較複雜,不是我們在應用中能控制的,是以盡量避免在url中使用非ASCII字元。

HTTP header的編解碼

同理,預設使用ISO編碼且不能改變,是以不用有非ASCII字元。

POST表單的編解碼

post使用body傳遞資料,而header中設定了contenttype,是以我們根據這個編碼格式進行編解碼即可。

http body的編解碼

上面講過了。

另外JDBC的編碼設定要和資料庫内置的資料編碼保持一緻。

在JS中的編碼問題

外部引入JS檔案

引入時需要設定編碼,否則可能亂碼

JS的URL編碼

其他需要編碼的地方

1 xml可以設定頭指定編碼格式

2 velocity模闆設定編碼

3 jsp設定編碼

常見問題分析

中文字元變亂碼

編碼解碼的字元集不一緻

一個漢字變成問号

将中文經過ISO編碼(不支援中文)後會變成?

一個漢字變成兩個問号

可能是多次編碼過程中出錯。

不正常的正确編碼

微信公衆号

個人公衆号:程式員黃小斜

微信公衆号【程式員黃小斜】新生代青年聚集地,程式員成長充電站。作者黃小斜,職業是阿裡程式員,身份是斜杠青年,希望和更多的程式員交朋友,一起進步和成長!專注于分享技術、面試、職場等成長幹貨,這一次,我們一起出發。

關注公衆号後回複“2020”領取我這兩年整理的學習資料,涵蓋自學程式設計、求職面試、算法刷題、Java技術學習、計算機基礎和考研等8000G資料合集。

JavaWeb技術内幕三:JavaWeb中文編碼問題幾種常見的編碼格式Java中需要編碼的場景Java中如何編解碼Java Web中設計的編解碼在JS中的編碼問題常見問題分析

技術公衆号:Java技術江湖

微信公衆号【Java技術江湖】一位阿裡 Java 工程師的技術小站,專注于 Java 相關技術:SSM、SpringBoot、MySQL、分布式、中間件、叢集、Linux、網絡、多線程,偶爾講點Docker、ELK,同時也分享技術幹貨和學習經驗,緻力于Java全棧開發!

關注公衆号後回複“PDF”即可領取200+頁的《Java工程師面試指南》強烈推薦,幾乎涵蓋所有Java工程師必知必會的知識點。

JavaWeb技術内幕三:JavaWeb中文編碼問題幾種常見的編碼格式Java中需要編碼的場景Java中如何編解碼Java Web中設計的編解碼在JS中的編碼問題常見問題分析

繼續閱讀