鍍金池/ 教程/ Java/ java編碼轉(zhuǎn)換過程
編碼詳情
java編碼轉(zhuǎn)換過程
認(rèn)識(shí)字符集
javaWeb中的編碼解碼
認(rèn)識(shí)字符集
總結(jié)
java是如何編碼解碼的
解決URL中文亂碼問題
JSP頁面編碼過程

java編碼轉(zhuǎn)換過程

前面三篇博客側(cè)重介紹字符、編碼問題,通過這三篇博客各位博友對(duì)各種字符編碼有了一個(gè)初步的了解,要了解java的中文問題這是必須要了解的。但是了解這些僅僅只是一個(gè)開始,以下博客將側(cè)重介紹java亂碼是如何產(chǎn)生的、存在哪些亂碼的情況、該如何從根本上解決亂碼問題。各位隨博主一起征服令人厭煩的java亂碼問題吧?。?!

java編碼轉(zhuǎn)換過程

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

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

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

3、直接運(yùn)行這些類或者部署在WEB容器中運(yùn)行,得到輸出結(jié)果。

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

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

System.out.println(System.getProperty("file.encoding"));

第二步:當(dāng)我們使用javac.exe編譯我們的java文件時(shí),JDK首先會(huì)確認(rèn)它的編譯參數(shù)encoding來確定源代碼字符集,如果我們不指定該編譯參數(shù),JDK首先會(huì)獲取操作系統(tǒng)默認(rèn)的file.encoding參數(shù),然后JDK就會(huì)把我們編寫的java源程序從file.encoding編碼格式轉(zhuǎn)化為JAVA內(nèi)部默認(rèn)的UNICODE格式放入內(nèi)存中。

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

在這一步中對(duì)對(duì)JSP源文件的處理方式有點(diǎn)兒不同:WEB容器調(diào)用JSP編譯器,JSP編譯器首先會(huì)查看JSP文件是否設(shè)置了文件編碼格式,如果沒有設(shè)置則JSP編譯器會(huì)調(diào)用調(diào)用JDK采用默認(rèn)的編碼方式將JSP文件轉(zhuǎn)化為臨時(shí)的servlet類,然后再編譯為.class文件并保持到臨時(shí)文件夾中。

第四步:運(yùn)行編譯的類:在這里會(huì)存在一下幾種情況

1、直接在console上運(yùn)行。

2、JSP/Servlet類。

3、java類與數(shù)據(jù)庫之間。

這三種情況每種情況的方式都會(huì)不同,

1.Console上運(yùn)行的類

這種情況下,JVM首先會(huì)把保存在操作系統(tǒng)中的class文件讀入到內(nèi)存中,這個(gè)時(shí)候內(nèi)存中class文件編碼格式為Unicode,然后JVM運(yùn)行它。如果需要用戶輸入信息,則會(huì)采用file.encoding編碼格式對(duì)用戶輸入的信息進(jìn)行編碼同時(shí)轉(zhuǎn)換為Unicode編碼格式保存到內(nèi)存中。程序運(yùn)行后,將產(chǎn)生的結(jié)果再轉(zhuǎn)化為file.encoding格式返回給操作系統(tǒng)并輸出到界面去。整個(gè)流程如下:

http://wiki.jikexueyuan.com/project/java-chinese-garbled-solution/images/4.1.png" alt="" />

在上面整個(gè)流程中,凡是涉及的編碼轉(zhuǎn)換都不能出現(xiàn)錯(cuò)誤,否則將會(huì)產(chǎn)生亂碼。

2.Servlet類

由于JSP文件最終也會(huì)轉(zhuǎn)換為servlet文件(只不過存儲(chǔ)的位置不同而已),所以這里我們也將JSP文件納入其中。

當(dāng)用戶請(qǐng)求Servlet時(shí),WEB容器會(huì)調(diào)用它的JVM來運(yùn)行Servlet。首先JVM會(huì)把servlet的class加載到內(nèi)存中去,內(nèi)存中的servlet代碼是Unicode編碼格式的。然后JVM在內(nèi)存中運(yùn)行該Servlet,在運(yùn)行過程中如果需要接受從客戶端傳遞過來的數(shù)據(jù)(如表單和URL傳遞的數(shù)據(jù)),則WEB容器會(huì)接受傳入的數(shù)據(jù),在接收過程中如果程序設(shè)定了傳入?yún)?shù)的的編碼則采用設(shè)定的編碼格式,如果沒有設(shè)置則采用默認(rèn)的ISO-8859-1編碼格式,接收的數(shù)據(jù)后JVM會(huì)將這些數(shù)據(jù)進(jìn)行編碼格式轉(zhuǎn)換為Unicode并且存入到內(nèi)存中。運(yùn)行Servlet后產(chǎn)生輸出結(jié)果,同時(shí)這些輸出結(jié)果的編碼格式仍然為Unicode。緊接著WEB容器會(huì)將產(chǎn)生的Unicode編碼格式的字符串直接發(fā)送置客戶端,如果程序指定了輸出時(shí)的編碼格式,則按照指定的編碼格式輸出到瀏覽器,否則采用默認(rèn)的ISO-8859-1編碼格式。整個(gè)過程流程圖如下:

http://wiki.jikexueyuan.com/project/java-chinese-garbled-solution/images/4.3.png" alt="" />

3.數(shù)據(jù)庫部分

我們知道java程序與數(shù)據(jù)庫的連接都是通過JDBC驅(qū)動(dòng)程序來連接的,而JDBC驅(qū)動(dòng)程序默認(rèn)的是ISO-8859-1編碼格式的,也就是說我們通過java程序向數(shù)據(jù)庫傳遞數(shù)據(jù)時(shí),JDBC首先會(huì)將Unicode編碼格式的數(shù)據(jù)轉(zhuǎn)換為ISO-8859-1的編碼格式,然后在存儲(chǔ)在數(shù)據(jù)庫中,即在數(shù)據(jù)庫保存數(shù)據(jù)時(shí),默認(rèn)格式為ISO-8859-1。

http://wiki.jikexueyuan.com/project/java-chinese-garbled-solution/images/4.4.png" alt="" />