[jsp]常見問題--Java 開發中遇到的亂碼問題

若想明白jsp開發過程中爲什麼會產生中文亂碼,我們先來看看unicode編碼。
Unicode (統一碼)顧名思義是一個將世界上各種文字統一在一起的東東。由美國各大電腦廠商組成的Unicode策進會來推動。目的,推廣一個世界通用的編碼體制,驚世界上所有常用的文字都涵蓋進去,從而減少個電腦商開發國外市場遇到的問題。
爲了將成千上萬的文字統統收集到一個共同的編碼機制下,在兼顧經濟的原則下,不管是東方還是西方文字,每個字在Unicode中一律以兩個Bytes來表示,這樣至少有2的16次方65536種不同的組合,足以應付目前絕大多數場合的需要。
基本上,計算機只是處理數字。它們指定一個數字,來儲存字母或其他字符。在創造Unicode之前,有數百種指定這些數字的編碼系統。沒有一個編碼可以包含足夠的字符:例如,單單歐州共同體就需要好幾種不同的編碼來包括所有的語言。即使是單一種語言,例如英語,也沒有哪一個編碼可以適用於所有的字母,標點符號,和常用的技術符號。
這些編碼系統也會互相沖突。也就是說,兩種編碼可能使用相同的數字代表兩個不同的字符,或使用不同的數字代表相同的字符。任何一臺特定的計算機(特別是服務器)都需要支持許多不同的編碼,但是,不論什麼時候數據通過不同的編碼或平臺之間,那些數據總會有損壞的危險。
Unicode給每個字符提供了一個唯一的數字,不論是什麼平臺,不論是什麼程序,不論什麼語言。Unicode標準已經被這些工業界的領導們所採用,例如:Apple, HP, IBM, JustSystem, Microsoft, Oracle, SAP, Sun, Sybase, Unisys和其它許多公司。最新的標準都需要Unicode,例如XML, Java, ECMAScript (JavaScript), LDAP, CORBA 3.0, WML等等,並且,Unicode是實現ISO/IEC 10646的正規方式。許多操作系統,所有最新的瀏覽器和許多其他產品都支持它。Unicode標準的出現和支持它工具的存在,是近來全球軟件技術最重要的發展趨勢。
將Unicode與客戶服務器或多層應用程序和網站結合,比使用傳統字符集節省費用。Unicode使單一軟件產品或單一網站能夠貫穿多個平臺,語言和國家,而不需要重建。它可將數據傳輸到許多不同的系統,而無損壞。
在與Unicode相關的各技術文件中,經常會看到ISO 10646和UCS這兩個名詞。
ISO是位於瑞士的國際標準局的縮寫。
UCS爲ISO頒佈的第10646號標準 Universal Character Set,就是世界通用字符集。
UCS通用字符集採用4個Bytes來編碼,將世界上所有的官用和商用編碼大小通吃,一網打盡。Unicode自1991年便和ISO的UCS小組密切配合,讓Unicode和ISO 10646保持一致。因此Unicode 自2.0版開始,便和 ISO 10646-1使用相同的編碼。
康熙字典中的漢字有4萬7千,如果再加上裏面沒有的簡體字,和不同寫法的日文字,那麼 Unicode6萬多的分配空間,光用來分配漢字就顯得捉禁見晝,更別說什麼泰文,阿拉伯等其他文字了。針對這個問題Unicode和UCS採用了[中日韓文整合](CJK Unification)的解決方案,把中日韓筆畫詳盡的漢字用同一個單碼錶示。
經過[中日韓文整合]的Unicode稱爲統漢字Unihan。
完整的Unicode4.0版可由http://www.unicode.org/Public/UNIDATA/Unihan.txt 下載。

UTF (Unicode/UCS Transformation Format),Unicode推薦使用UTF-8和UTF-16兩種格式其中8和16指的是Bits數而不是Bytes數。
UTF-16基本就是Unicode雙字節的實現,加上一個應付未來需要的擴充編碼機制(很少用)
UTF-8 是一種不等幅的編碼方式,英數字(Ascii字碼)保持原狀,完全不受影響(因此不需要做轉換),而其他漢字資料須透過程序來轉換,會[變胖],因爲每個字需要額外一個或兩個Bytes來編碼。
UCS字符集中,有UCS-2和UCS-4等編碼方式其中的2和4指的是bytes數,對應UTF-8和UTF-16.
UCS-2基本和Unicode雙byte 編碼差不多
UCS-4四 byte編碼表示一個字,在每個 UCS-2前面加上兩個空白的Byte,便可得到對應的 UCS-4。

Unicode的空間分配:
以下Unicode區位碼均以16進製表示
Unicode的前256個字符和ISO-8859-1(西歐字母)完全相同,其中前半段就是Ascii(u+0000到u+00FF)。每個ISO-8859-1碼前面補上一個空byte(0x00)後纔是相應的Unicode碼。
和我們切身相關的Unihan主要分佈在u+3400到u+F9FFF之間,GB2312和BIG5主要分佈在u+4E00到U+9FFF之間。

UTF-8的編碼原理和特性:
知道了西歐字符和漢字在Unicode中的位置後,來看看UTF-8

U+0000~U+007E 1 _ _ _ _ _ _ _ (7bits)
U+0080~U+07FF 1 1 0_ _ _ _ _ 1 0_ _ _ _ _ _ (11bits)
U+0800~U+FFFF 1 1 1 0 _ _ _ _ 1 0 _ _ _ _ _ _ 1 0 _ _ _ _ _ _ (16bits)
看一看Unicode三種格式提出自由的bits(下劃線空位)是否足以用來代表區位中各Unicode碼,剛好夠用。
那麼當程序處理UTF-8編碼文件時,如何得知一個字符的疆界落在哪裏?還有到底他是以三種形式那一中出現呢?
每個以UTF-8編碼的字符,不管是以一、二、三個bytes出現,第一個byte前端都清楚地標示了該字符的byte總數。如110種有兩個1,代表這種字符是以第二種方式出現,由兩個bytes組成。而1110有三個1,表示這種字符一點種方式出現,由三個字節組成。
每個多重byte的UTF-8編碼有一個共同的通性,即其中的第二個第三個byte, 一律以10兩個bits開頭。由於其中的最高位總設成1,可以很容易和那些在UTF-8中只用一個Byte的ASCII字元區分開來,方便偵錯。
因爲上述設計特點,UTF-8和Unicode之間,可以很容易做雙向自由轉換,而不會丟失任何資料。
 解決辦法:亂碼問題在 NT操作系統我沒怎麼碰到過,但是在UNIX 或LINUX系統上出現的比較多
由於操作系統和使用環境不一樣,產生亂碼的方式也不一樣,但是如果掌握了上面的Unicode 編碼原理,自己仔細分析一下,很多問題便可迎刃而解。
下面看看幾個常見的例子。
1. 如果一些網站服務器例如Tomcat 如果遇到中文亂碼問題,可以修改conf目錄下的server.xml
<Connector port="8080" maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
enableLookups="false" redirectPort="8443" acceptCount="100" debug="0"connectionTimeout="20000" disableUploadTimeout="true" URIEncoding="GBK"/>
URIENcoding 設成GBK或GB2312
2. 表單中或傳遞字符串:本來輸入的漢字是正常的,但是提交後再顯示出來是亂碼,因爲提交的一般是 ISO8859編碼,所以顯示的時候要轉成GB2312編碼:

String S=new String(rs.getString("news").getBytes("gb2312"),"ISO8859_1");
//rs爲待轉換的字符串
然後使用S字符串的值就可以了
3. 有的服務器端的語言環境如果設成簡體中文的也可以解決此類問題
4. 插入數據庫中的字符是亂碼
看看數據庫中支持的是何種編碼方式,用類似2中的方式作一下轉換即可。
5. 總之,用jsp開發,碰到亂碼,你得分析是讀的時候發生亂碼,還是寫的時候發生亂碼,用2中的轉換,基本就能解決問題,有些時候寫的時候做一次轉換,例如:
String S=new String(rs.getString("news").getBytes("gb2312"),"ISO8859_1");
//讀的時候在轉換回來
String S=new String(rs.getString("news").getBytes("ISO8859_1"),"GB2312");
或者把ISO8859-1和GB2312 的位置換一下,自己多試試,就能找到解決問題的辦法。

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