1. 程式人生 > >java編碼轉換過程(轉自http://cmsblogs.com/?p=1475)

java編碼轉換過程(轉自http://cmsblogs.com/?p=1475)

tex src bytes .com 設定 界面 console 獲取 java程序

一、java編碼轉換過程(轉自http://cmsblogs.com/?p=1475

我們總是用一個java類文件和用戶進行最直接的交互(輸入、輸出),這些交互內容包含的文字可能會包含中文。無論這些java類是與數據庫交互,還是與前端頁面交互,他們的生命周期總是這樣的:

1>程序員在操作系統上通過編輯器編寫程序代碼並且以.java的格式保存操作系統中,這些文件我們稱之為源文件。

2>通過JDK中的javac.exe編譯這些源文件形成.class類。

3>直接運行這些類或者部署在WEB容器中運行,得到輸出結果。

這些過程是從宏觀上面來觀察的,了解這個肯定是不行的,我們需要真正來了解java是如何來編碼和被解碼的:

第一步:當我們用編輯器編寫java源文件,程序文件在保存時會采用操作系統默認的編碼格式(一般我們中文的操作系統采用的是GBK編碼格式)形成一個.java文件。java源文件是采用操作系統默認支持的file.encoding編碼格式保存的。下面代碼可以查看系統的file.encoding參數值。

技術分享

第二步:當我們使用javac.exe編譯我們的java文件時,JDK首先會確認它的編譯參數encoding來確定源代碼字符集,如果我們不指定該編譯參數,JDK首先會獲取操作系統默認的file.encoding參數,然後JDK就會把我們編寫的java源程序從file.encoding編碼格式轉化為JAVA內部默認的UNICODE格式放入內存中。

第三步:JDK將上面編譯好的且保存在內存中信息寫入class文件中,形成.class文件。此時.class文件是Unicode編碼的,也就是說我們常見的.class文件中的內容無論是中文字符還是英文字符,他們都已經轉換為Unicode編碼格式了。

第四步:運行編譯的類:在這裏會存在一下幾種情況

1>直接在console上運行。

2>JSP/Servlet類。

3>java類與數據庫之間。

這三種情況每種情況的方式都會不同

①Console上運行的類

這種情況下,JVM首先會把保存在操作系統中的class文件讀入到內存中,這個時候內存中class文件編碼格式為Unicode,然後JVM運行它。如果需要用戶輸入信息,則會采用file.encoding編碼格式對用戶輸入的信息進行編碼同時轉換為Unicode編碼格式保存到內存中。程序運行後,將產生的結果再轉化為file.encoding格式返回給操作系統並輸出到界面去。整個流程如下:

技術分享

②Servlet類

由於JSP文件最終也會轉換為servlet文件(只不過存儲的位置不同而已),所以這裏我們也將JSP文件納入其中。

當用戶請求Servlet時,WEB容器會調用它的JVM來運行Servlet。首先JVM會把servlet的class加載到內存中去,內存中的servlet代碼是Unicode編碼格式的。然後JVM在內存中運行該Servlet,在運行過程中如果需要接受從客戶端傳遞過來的數據(如表單和URL傳遞的數據),則WEB容器會接受傳入的數據,在接收過程中如果程序設定了傳入參數的的編碼則采用設定的編碼格式,如果沒有設置則采用默認的ISO-8859-1編碼格式,接收的數據後JVM會將這些數據進行編碼格式轉換為Unicode並且存入到內存中。運行Servlet後產生輸出結果,同時這些輸出結果的編碼格式仍然為Unicode。緊接著WEB容器會將產生的Unicode編碼格式的字符串直接發送置客戶端,如果程序指定了輸出時的編碼格式,則按照指定的編碼格式輸出到瀏覽器,否則采用默認的ISO-8859-1編碼格式。(UNICODE編碼的servlet的class->內存;jvm將表單、url傳進來的數據按照默認或者設定的編碼格式轉換為Unicode->內存;如果沒有指定輸出的編碼格式則web容器會將Unicode編碼的字符串發送至客戶端)

技術分享

③數據庫部分

我們知道java程序與數據庫的連接都是通過JDBC驅動程序來連接的,而JDBC驅動程序默認的是ISO-8859-1編碼格式的,也就是說我們通過java程序向數據庫傳遞數據時,JDBC首先會將Unicode編碼格式的數據轉換為ISO-8859-1的編碼格式,然後在存儲在數據庫中,即在數據庫保存數據時,默認格式為ISO-8859-1。

技術分享

二、getBytes

把JVM內存中unicode形式的String按encoding制定的編碼,轉成字節流,比如漢字"分":
String="分"
String.getBytes("utf-8")//把String轉成utf-8字節流,漢字"分"為3個字節[0xe5,0x88,0x86]

String.getBytes("gbk")//把String轉成gbk字節流,漢字"分"為2個字節[0xb7,0xd6]

三、編碼解碼(非轉載)

通常意義上的解碼大致是這樣一種情況:一個GB2312編碼的字符串“aaa”的字節碼被發送到一個接收處,這個接收處使用Unicode編碼,這個時候就會產生亂碼(因為這個時候明明是GB2312的字節碼卻被編碼成了Unicode字符),怎麽解決呢?先用Unicode方式解碼,然後用GB2312重新編碼即可。

下面的解釋我覺得更清楚些:

1.傳輸過來的字節碼是用utf-8編碼的,假設字節碼為b。
2.你獲得的那個字符串,假設為s,是用gbk對b進行編碼獲得的字符串,所以是亂碼。
3.你使用gbk對s進行解碼,用utf-8再編碼,於是獲得了原來的b

java編碼轉換過程(轉自http://cmsblogs.com/?p=1475)