java 中的編碼問題
一、編碼格式:
1.ASCII 總共128個 2.ISO-8859-1 共256個,涵蓋了大部分西歐語言字元 3.GB2312 包含682個符號,6763個漢字
4.GBK相容GB3212,包含21003個漢字 5.GB13030 相容GB2312 《資訊交換用漢字編碼字元集》 國家標準
6.UTF-16 Unicode編碼,用兩個位元組表示一個字元,java中以UTF-16作為記憶體中的字元儲存格式。
7.UTF-8 採用變長技術,每個編碼地區有不同的字碼長度,不同類型的字元可以由1~6個位元組組成。
二、java中的編碼情境
1.I/O操作中的編碼操作
//寫入檔案
String file="c:/a.txt";
String charset="UTF-8";
FileOutputStram os =new FileOutputStram(file);
OutputStreamWriter writer=new OutputStreamWriter(os,charset);//如果此處不設定charset會有預設值
try{
writer.write("這是儲存的中文字元");
}finally{
writer.close();
}
//讀取檔案
FileInputStream is=new FileInputStream();
InputStreamReader reader=new InputStreamReader(is,charset);//讀檔案時charset必須與寫檔案時一致或相容,否則會亂碼
StringBuilder sb=new StringBuilder();
char[] buf = new char[64];
int count = 0;
try{
while(count = reader.read(buf)){
sb.append(buf,0,count);
}
}finally{
reader.close();
}
2.記憶體中的編碼操作
//字串與位元組數組之間的轉換
String str="這是一段中文字元";
byte[] b=srt.getBytes("UTF-8");//將字串轉換成byte數組,必須設定編碼格式,否則使用預設值
String n=new String(b,"UTF-8");
//字串 編碼成位元組數組 解碼成字元數組
String str="這是一段中文字元";
Charset charset=Charset.forName("UTF-8");
ByteBuffer byteBuffer=charset.encode(str);
CharBuffer charBuffer=charset.decode(byteBuffer);
三、編碼格式比較
GBK與GB2312,GBK可以處理所有的中文字元,而GB2312則有許多字元處理不了,所以應選擇GBK。
UTF-8與UTF-16,都是處理Unicode編碼,兩者編碼規則不相同,相對來說UTF-16編碼效率高,任何字元都使用兩個位元組16位來儲存,字元到字
節之間的轉換更簡單,進行字串操作也更好,適合在本地磁碟與記憶體之間使用,java在記憶體中的編碼使用UTF-16。UTF-16編碼成的位元組流在
傳輸過程中如果出現資料丟失則,所有資料都將導致解碼失敗。UTF-8變長編碼,針對ASCII字元採用單位元組儲存,適合網路傳輸,每個字元都
有開始和結束的識別資訊,網路傳輸過程中,如果不分資料丟失,解碼時僅僅是丟失不分不能解碼。UTF-8編碼效率介於UTF-16與GBK之間,
UTF-8在編碼效率上和編碼安全上做了平衡,是理想的中文編碼方式。
四、java Web中設計的編碼與解碼
1.Web中存在編解碼的地方:
使用者從瀏覽器發送一個HTTP請求到伺服器,需要編碼的地方有:URL,Cookie,parameter。伺服器接收到請求後需要解碼的地方有URI,Cookie
,post表單參數。伺服器端可能還需要讀取資料庫中的資料,讀取本地或網路中的其他檔案,等等。服務端處理完請求後還需要將資料再編碼
然後通過socket發送到使用者的瀏覽器裡。瀏覽器再將相應資訊解碼並展示出來。
2.URL的編解碼的地方
串連的組成部分:如下連結
http://www.360buy.com/團購/Search?keyword=中跟鞋(此連結僅是個例子)
此連結可分為幾個部分:①scheme:http:②網域名稱:www.360buy.com③URI:團購/Search④queryString:keyword=中跟鞋
URI(/團購/Search)中如果有中文,編碼在Tomcat中設定,<connector URIEncoding="UTF-8"/>,如果沒有定義,則使用預設的iso-8859-1進
行編解碼。
queryString(keyword=中跟鞋)中如果有中文,此部分是編碼設定在tomcat中,<connector URIEncoding="UTF-8"
useBodyEncodingForURI="true"/>,如果這樣設定,則編碼方式與URI的編碼格式一致,如果不設定useBodyEncodingForURI="true",則使用預設
的編碼格式,不同瀏覽器有不同的預設值。解碼則是在第一次調用request.getParameter("...")時進行解碼的,如果設定了
useBodyEncodingForURI="true",則可以預設使用URIEncoding="UTF-8"設定的參數進行解碼。
在使用get請求的時候參數最好不要使用中文,比較容易出現亂碼問題。URI部分也不建議使用中文。Tomcat中最好設定成<connector
URIEncoding="UTF-8" useBodyEncodingForURI="true"/>,並保持整個應用中編解碼都一致。
3.post請求的編解碼:
在用戶端使用post提交表單時,首先在用戶端會使用ContentType 中設定的charset對錶單進行編碼,在服務端第一次調用
request.getParameter("...")時也會自動使用ContentType 中設定的charset進行解碼,當然還可以在第一次調用request.getParameter
("...")之前,通過request.setCharacterEncoding(charset)來設定解碼方式。post提交表單一般不會出現問題。
4.HTTP Header的編解碼
先說解碼,Header中的解碼也是在第一次調用request,getHeader()時進行解碼的,如果調用時還沒有解碼,則調用MessageBytes.toString方
法,這個方法將從byte到char使用預設的ISO-8859-1進行解碼。此處不能設定Header的其他解碼格式,所以如果Header中有非ASCII字元則必然
會亂碼。如果在Header中必須有中文則必須顯示將其轉換成ASCII字元。
5.HTTP body中的編解碼
編碼:通過response.setCharacterEncoding(charset)進行編碼,資料轉送到瀏覽器後,通過Header中的<meta HTTP-equiv="Content-Type"
content="text/html";charset=UTF-8"/>中的charset來進行解碼,如果沒有設定,則使用瀏覽器預設的解碼方式。
稍後將詳解js中的編碼問題
歡迎加入程式員群:134994493