簡單記錄下Java web 中的中文編碼問題

看了《深入分析java web技術內幕》,感覺編碼這部分寫的挺有總結性的,自己總結了書上的內容,記錄下一些知識點,希望能有更多朋友受益O(∩_∩)O

1.哪些操作中會存在編碼?

1.1)I/O操作中存在的編碼:在I/O中,字符與字節之間的相互轉換 的操作中,通常用到InputStreamReaderOutputStreamWriter 實現,要注意使用統一的編解碼字符集,一般就不會出現亂碼問 題

1.2)內存操作中存在的編碼:

字符串—>字節:String對象.getBytes(String charset);

字節—>字符串:new String(byte[] b,String charset);

2.使用Charset類進行編碼與解碼:

Charset charset = Charset.forName(String charset);

編碼:ByteBuffer byteBuffer = charset.encode(String s);

解碼:CharBuffer charBuffer = charset.decode(ByteBuffer b);

ByteBuffer類提供一個緩衝區實現對字符與字節的軟件換,無需編碼與解碼,實際值並沒修改,僅僅類型做了轉換,把16bit char變成兩個8bitbyte

ByteBuffer byteBuffer = ByteBuffer.allocate(int bufferSize); 

//初始化分配一個緩衝區

byteBuffer.putChar(Char char); //字符—>字節

byteBuffer.getChar(int index); //字節—>字符

3.Java中如何編解碼:

3.1)根據指定的字符集通過Charset.forName(String charset)創建    Charset類;

3.2)根據Charser類創建CharsetEncoder對象;

3.3)調用CharsetEncoder.encode(String s)進行編碼


4.Java web中哪些地方可能存在編碼轉換:

4.1)發起HTTP請求時:URLCookie、請求參數

4.2)服務端響應時:讀取的數據庫數據、本地或網絡中的文本文件



4.3)URL上的編解碼:


在URL組成中,可能出現中文的部分有Path InfoQuery String 這兩部分,且瀏覽器對這兩部分採取不同的編碼,不同瀏覽器對 Path Info部分的編碼也不一樣;Query String部分的解碼字符集是 通過HTTPHeader傳到服務器端的,其字符集要麼是通過 Header中的ContentType定義的charset,要麼就是默認的 ISO-8859-1,要是有Header中定義的需要做一些相應的配置

tomcat中,對URL中的URI部分進行解碼的字符集是在connector<Connector URIEncoding=”UTF-8” />中定義的,若沒定義則使用ISO-8859-1解析,故有中文URL時最好把URIEncoding設爲UTF-8;獲取Query String部分是通過request.getParameter方法實現的,之後進行解碼;對於Query String部分要使用ContentType中定義的編碼就需要在connector<Connector URIEncoding=”UTF-8” useBodyEncodingForURI=”true” />中的useBodyEncodingForURI設置爲true,該設置僅僅是對Query String部分使用BodyEncoding編碼,故在服務器端最好設置<Connector/>中的URIEncodinguseBodyEncodingForURI這兩個參數

4.4)HTTP Header的編解碼:

tomcat中,對Header中的項進行解碼是在調用 request.getHeader 方法時進行的,若請求的Header項沒有解碼 則調用MessageBytestoString方法,該方法從bytechar 的轉換使用的默認編碼是 ISO-8859-1,若設置的Header中有ASCII字符解碼肯定會有亂 碼,所以儘量不要在Header 傳遞非ASCII字符,若必需傳遞,先用 org.apache.catalina.util.URLEncoding編碼後添加到Header 中,屆時再用對應的字符集解碼即可

4.5)POST表單的編解碼:

POST表單進行解碼是在第一次調用request.getParameter方法 時發生的;當提交POST表單時,瀏覽器先根據ContentTypeCharset編碼格式對錶單內容進行編碼,後提交到服務器端, 在服務器端也是用ContentTypeCharset進行解碼的,故表 單提交一般不會出現亂碼,但一定要在第一次調用 request.getParameter 前就設置 request.setCharacterEncoding(charset),否則也可能有亂 碼,若 沒設置則使用默認的ISO-8859-1編碼;對於 multipart/form-data類型參數,同樣使用Content-Type定義的字 符集編碼,上傳文件使用字節流方式傳輸到服務器的本地目 錄,此過程不涉及字符編碼,在將文件內容添加到parameters 時才發生編碼,如果用這個不能編碼則採用默認的 ISO-8859-1編碼

4.6)HTTP BODY的編解碼:

服務端響應客戶端的請求返回資源這一過程,要先編碼再瀏覽 器解碼,可通過response.setCharacterEncoding設置,該設置會 覆蓋request.setCharacterEncoding的值,並通過Content-Type 返回瀏覽 器,瀏覽器接收時用Content-Type進行解碼;若 Header中的Content-Type沒有設置,則根據HTML中的<meta  http-equiv=”Context-Type” content=”text/html; charset=UTF-8”  />中的charser進行解碼,HTML中的再無設置則使用默認的編 碼來解碼

4.7)對於數據庫編碼問題,可以通過設置JDBCURL來指定

如: url=”jdbc:mysql://localhost:3306/DB?useUnicode=true&characte rEn coding=UTF-8”

4.8)JS中的編碼問題:

外部引入js文件:

<script src=” ” charset=”UTF-8”></script>

引入一個包含中文的js文件,如果script標籤上沒有設 置 charset,則瀏覽器以當前頁面默認的字符集解析該js文件;若 外部js文件與當前頁面的編碼格式一致,則可以不用設置 charset;若不設置charsetjs文件編碼格式與當前頁面不一 致,則亂碼

4.9)JSURL編碼:

escape(String s)函數:將ASCII字母、數字、標點符號之外的 其他字符轉換成Unicode編碼值,並在其編碼值前加“%u”; 解碼用unescape(String s)函數,可以防止信息丟失

(上述兩個方法一般用encodeURLencodeURLComponent 替)

encodeURL(String s)函數:可以將整個URL中的字符(除特殊 字符外)進行UTF-8編碼,在每個碼值前加“%”;解碼使用 decodeURL(String s)函數

encodeURLComponent()函數:除了對 ‘ ( ) * - . _ ~ 0-9 a-z A-Z 不編碼外,其餘都編碼,通常用於將一個URL當做一個參數 放在另一個URL中;解碼通過decodeURLComponent(String s) 函數

4.10)javajs編碼問題:

Java端處理URL編解碼有兩個類,java.net.URLEncoder java.net.URLDecoder,分別對應前端js encodeURLComponent 與decodeURLComponent;在前端使encodeURLComponent 碼後,到服務端使用URLDecoder 解碼可能會發生亂碼,原因是 前端js的默認編碼是UTF-8 而後端對於中文的編碼一般是GBKGB2312,用GBK 解碼UTF-8的編碼,必定發生亂碼;解決方法:用 encodeURLComponent去編碼2次,即 encodeURLComponent(encodeURLComponent(String s)),這樣 在使用request.getParameterGBK解碼後取得的就是UTF-8 編碼的字符串,若在java端要使用該字符串,再用UTF-8 碼就可以;若是這個結果直接通過js輸出到前端,則該UTF-8 字符串輸出可以正常顯示

4.11)其他需要編碼的地方:

除了URL和參數編碼的問題外,XMLVelocityJSP等也可 能存在編碼

XML<?xml version=”1.0” encoding=”UTF-8”?>

Velocityservices.VelocityService.input.encoding=UTF-8

JSP<% @page contentType=”text/html; charset=UTF-8”%>


PS:以上圖片摘自《深入java web 技術內幕》

發佈了32 篇原創文章 · 獲贊 10 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章