http中的編碼以及String.getBytes()

在Java中,String的getBytes()方法是獲得一個操做系統默認的編碼格式的字節數組。這個表示在不通OS下,返回的東西不同! 


String.getBytes(String decode)方法會根據指定的decode編碼返回某字符串在該編碼下的byte數組表示,如 

byte[] b_gbk = "中".getBytes("GBK"); 
byte[] b_utf8 = "中".getBytes("UTF-8"); 
byte[] b_iso88591 = "中".getBytes("ISO8859-1"); 


將分別返回「中」這個漢字在GBK、UTF-8和ISO8859-1編碼下的byte數組表示,此時b_gbk的長度爲2,b_utf8的長度爲3,b_iso88591的長度爲1。 

而與getBytes相對的,能夠經過new String(byte[], decode)的方式來還原這個「中」字時,這個new String(byte[], decode)實際是使用decode指定的編碼來將byte[]解析成字符串。 

String s_gbk = new String(b_gbk,"GBK"); 
String s_utf8 = new String(b_utf8,"UTF-8"); 
String s_iso88591 = new String(b_iso88591,"ISO8859-1"); 

經過打印s_gbk、s_utf8和s_iso88591,會發現,s_gbk和s_utf8都是「中」,而只有s_iso88591是一個不認識的字符,爲何使用ISO8859-1編碼再組合以後,沒法還原「中」字呢,其實緣由很簡單,由於ISO8859-1編碼的編碼表中,根本就沒有包含漢字字符,固然也就沒法經過"中".getBytes("ISO8859-1");來獲得正確的「中」字在ISO8859-1中的編碼值了,因此再經過new String()來還原就無從談起了。 

所以,經過String.getBytes(String decode)方法來獲得byte[]時,必定要肯定decode的編碼表中確實存在String表示的碼值,這樣獲得的byte[]數組才能正確被還原。 

有時候,爲了讓中文字符適應某些特殊要求(如http header頭要求其內容必須爲iso8859-1編碼),可能會經過將中文字符按照字節方式來編碼的狀況,如 

String s_iso88591 = new String("中".getBytes("UTF-8"),"ISO8859-1"), 

這樣獲得的s_iso8859-1字符串實際是三個在 ISO8859-1中的字符,在將這些字符傳遞到目的地後, 

目的地程序再經過相反的方式String s_utf8 = new String(s_iso88591.getBytes("ISO8859-1"),"UTF-8")來獲得正確的中文漢字「中」。這樣就既保證了遵照協議規定、也支持中文。 


=================================================== 

JAVA編碼轉換的詳細過程 

咱們常見的JAVA程序包括如下類別: 
       *直接在console上運行的類(包括可視化界面的類) 
       *JSP代碼類(注:JSP是Servlets類的變型) 
       *Servelets類 
       *EJB類 
       *其它不能夠直接運行的支持類 
這些類文件中,都有可能含有中文字符串,而且咱們經常使用前三類JAVA程序和用戶直接交互,用於輸出和輸入字符,如:咱們在JSP和Servlet中獲得客戶端送來的字符,這些字符也包括中文字符。不管這些JAVA類的做用如何,這些JAVA程序的生命週期都是這樣的: 
*編程人員在必定的操做系統上選擇一個合適的編輯軟件來實現源程序代碼並以.java擴展名保存在操做系統中,例如咱們在中文win2k中用記事本編輯一個java源程序; 
       *編程人員用JDK中的javac.exe來編譯這些源代碼,造成.class類(JSP文件是由容器調用JDK來編譯的); 
       *直接運行這些類或將這些類佈署到WEB容器中去運行,並輸出結果。 
      那麼,在這些過程當中,JDK和JVM是如何將這些文件如何編碼和解碼並運行的呢? 
      這裏,咱們以中文win2k操做系統爲例說明JAVA類是如何來編碼和被解碼的。 
第一步,咱們在中文win2k中用編輯軟件如記事本編寫一個Java源程序文件(包括以上五類JAVA程序),程序文件在保存時默認採用了操做系統默認支持GBK編碼格式(操做系統默認支持的格式爲file.encoding格式)造成了一個.java文件,也即,java程序在被編譯前,咱們的JAVA源程序文件是採用操做系統默認支持的file.encoding編碼格式保存的,java源程序中含有中文信息字符和英文程序代碼;要查看系統的file.encoding參數,能夠用如下代碼: 
public class ShowSystemDefaultEncoding { 
public static void main(String[] args) { 
String encoding = System.getProperty("file.encoding"); 
System.out.println(encoding); 
}} 
第二步,咱們用JDK的javac.exe文件編譯咱們的Java源程序,因爲JDK是國際版的,在編譯的時候,若是咱們沒有用-encoding參數指定咱們的JAVA源程序的編碼格式,則javac.exe首先得到咱們操做系統默認採用的編碼格式,也即在編譯java程序時,若咱們不指定源程序文件的編碼格式,JDK首先得到操做系統的file.encoding參數(它保存的就是操做系統默認的編碼格式,如WIN2k,它的值爲GBK),而後JDK就把咱們的java源程序從file.encoding編碼格式轉化爲JAVA內部默認的UNICODE格式放入內存中。而後,javac把轉換後的unicode格式的文件進行編譯成.class類文件,此時.class文件是UNICODE編碼的,它暫放在內存中,緊接着,JDK將此以UNICODE編碼的編譯後的class文件保存到咱們的操做系統中造成咱們見到的.class文件。對咱們來講,咱們最終得到的.class文件是內容以UNICODE編碼格式保存的類文件,它內部包含咱們源程序中的中文字符串,只不過此時它己經由file.encoding格式轉化爲UNICODE格式了。這一步中,對於JSP源程序文件是不一樣的,對於JSP,這個過程是這樣的:即WEB容器調用JSP編譯器,JSP編譯器先查看JSP文件中是否設置有文件編碼格式,若是JSP文件中沒有設置JSP文件的編碼格式,則JSP編譯器調用JDK先把JSP文件用JVM默認的字符編碼格式(也即WEB容器所在的操做系統的默認的file.encoding)轉化爲臨時的Servlet類,而後再把它編譯成UNICODE格式的class類,並保存在臨時文件夾中。如:在中文win2k上,WEB容器就把JSP文件從GBK編碼格式轉化爲UNICODE格式,而後編譯成臨時保存的Servlet類,以響應用戶的請求。 
      第三步,運行第二步編譯出來的類,分爲三種狀況: 
      A、 直接在console上運行的類 
      B、 EJB類和不能夠直接運行的支持類(如JavaBean類) 
      C、 JSP代碼和Servlet類 
      D、 JAVA程序和數據庫之間 
下面咱們分這四種狀況來看。 
A、直接在console上運行的類 
這種狀況,運行該類首先須要JVM支持,即操做系統中必須安裝有JRE。運行過程是這樣的:首先java啓動JVM,此時JVM讀出操做系統中保存的class文件並把內容讀入內存中,此時內存中爲UNICODE格式的class類,而後JVM運行它,若是此時此類須要接收用戶輸入,則類會默認用file.encoding編碼格式對用戶輸入的串進行編碼並轉化爲unicode保存入內存(用戶能夠設置輸入流的編碼格式)。程序運行後,產生的字符串(UNICODE編碼的)再回交給JVM,最後JRE把此字符串再轉化爲file.encoding格式(用戶能夠設置輸出流的編碼格式)傳遞給操做系統顯示接口並輸出到界面上。以上每一步的轉化都須要正確的編碼格式轉化,才能最終不出現亂碼現象。 
B、EJB類和不能夠直接運行的支持類(如JavaBean類) 
因爲EJB類和不能夠直接運行的支持類,它們通常不與用戶直接交互輸入和輸出,它們經常與其它的類進行交互輸入和輸出,因此它們在第二步被編譯後,就造成了內容是UNICODE編碼的類保存在操做系統中了,之後只要它與其它的類之間的交互在參數傳遞過程當中沒有丟失,則它就會正確的運行。 
C、JSP代碼和Servlet類 
通過第二步後,JSP文件也被轉化爲Servlets類文件,只不過它不像標準的Servlets一校存在於classes目錄中,它存在於WEB容器的臨時目錄中,故這一步中咱們也把它作爲Servlets來看。 
對於Servlets,客戶端請求它時,WEB容器調用它的JVM來運行Servlet,首先,JVM把Servlet的class類從系統中讀出並裝入內存中,內存中是以UNICODE編碼的Servlet類的代碼,而後JVM在內存中運行該Servlet類,若是Servlet在運行的過程當中,須要接受從客戶端傳來的字符如:表單輸入的值和URL中傳入的值,此時若是程序中沒有設定接受參數時採用的編碼格式,則WEB容器會默認採用ISO-8859-1編碼格式來接受傳入的值並在JVM中轉化爲UNICODE格式的保存在WEB容器的內存中。Servlet運行後生成輸出,輸出的字符串是UNICODE格式的,緊接着,容器將Servlet運行產生的UNICODE格式的串(如html語法,用戶輸出的串等)直接發送到客戶端瀏覽器上並輸出給用戶,若是此時指定了發送時輸出的編碼格式,則按指定的編碼格式輸出到瀏覽器上,若是沒有指定,則默認按ISO-8859-1編碼發送到客戶的瀏覽器上。 
D、Java程序和數據庫之間 
對於幾乎全部數據庫的JDBC驅動程序,默認的在JAVA程序和數據庫之間傳遞數據都是以ISO-8859-1爲默認編碼格式的,因此,咱們的程序在向數據庫內存儲包含中文的數據時,JDBC首先是把程序內部的UNICODE編碼格式的數據轉化爲ISO-8859-1的格式,而後傳遞到數據庫中,在數據庫保存數據時,它默認即以ISO-8859-1保存,因此,這是爲何咱們經常在數據庫中讀出的中文數據是亂碼。html

相關文章
相關標籤/搜索