字符串編碼問題的原理

字符串編碼(charset, encoding/decoding)問題原理 

編碼問題很重要,關於編碼問題的文章也很多。我本來沒有興趣重複這個主題。 
一個朋友問我有沒有比較好的編碼介紹文章。我記得以前看過幾篇很不錯的,但是當時搜索到的時候,就比較費勁,一時想不起來。於是,我就說,我攢一篇好了。 

--------------------------------------- 

編碼無處不在。Database, file, editor, IDE, compiler, browser。 
代碼(比如java, jsp, asp, php, python, ruby etc)裏面的字符串比較麻煩,涉及到editor, compiler, interpreter等等。 
所以,我的做法是,從來不在代碼裏面直接寫字符串資源,尤其是雙字節編碼的字符串資源。 
都是把字符串資源分離到一個單獨的資源文件裏面。這樣,只需要照管這個文件的編碼就夠了。 
需要注意的一點是,文件裏面、數據庫裏面、網絡傳輸需要的數據,都是byte[]。 
以下的討論,不涉及代碼裏面的字符串編碼問題。只討論系統運行起來之後,各部分之間的編碼問題。 

先說Java。 
JVM裏面的任何字符串資源都是Unicode,就是說,任何String類型的數據都是Unicode編碼。沒有例外。既然只有一種編碼,那麼,我們可以這麼說,JVM裏面的String是不帶編碼的。String相當於 char[]。 
JVM裏面的 byte[] 數據是帶編碼的。比如,Big5,GBK,GB2312,UTF-8之類的。 
一個GBK編碼的byte[] 轉換成 String,其實就是從GBK編碼向Unicode編碼轉換。 
一個String轉換成一個Big5編碼的byte[],其實就是從Unicode編碼向Big5編碼轉換。 
所以,Unicode是所有編碼轉換的中間介質。所有的編碼都有一個轉換器可以轉換到Unicode,而Unicode也可以轉換到其他所有的編碼。這樣構成了一個總線結構。 
比如,如果總共有10種編碼,那麼只需要 10 + 10 = 20個轉換器就夠了。如果要是兩兩直接轉換,那麼,需要的轉換器數量是一個組合數字,需要90個轉換器。 

一個系統的不同部分,都有自己的編碼。比如,數據庫,文件,JVM,瀏覽器這4個部分。 
在這些部分之間數據交換的地方,就會出現編碼問題。比如,數據庫和JVM之間,文件和JVM之間,瀏覽器和JVM之間。這些問題的原理都是相通的。 

編碼問題最容易處理的地方是文件和JVM之間。文件IO API帶有encoding 參數,請自行查閱。 
最不容易出現編碼問題的地方是數據庫和JVM之間。這應該是數據庫JDBC連接的基本功能。本文不專門進行討論。 
最容易出問題的地方是瀏覽器和服務器JVM之間(其實,代碼裏面的字符串更容易出問題,不過,我已經事先聲明,本文不討論代碼中的字符串編碼)。下面主要討論這塊瀏覽器和服務器JVM之間的編碼問題。 

我們把瀏覽器編碼叫做 Browser_Charset,把JVM編碼叫做JVM_Charset(通常等於服務器系統編碼)。 
當瀏覽器的數據過來的時候,是一個帶有Browser_Charset的byte[]。 
如果用戶處理程序需要一個String類型的數據,那麼JVM會好心好意地把這個byte[]轉換成String。使用的轉換器是 JVM_Charset -> Unicode。 
注意,如果這個時候,Browser_Charset 和 JVM_Charset並不相等。那麼,這個自動轉換是錯誤的。 
爲了彌補這個錯誤。我們需要做兩步工作。 
(1) Unicode -> JVM_Charset,把這個String 轉換回到原來的 byte[]。 
(2) Browser_Charset -> Unicode,把這個還原的byte[]轉換成 String。 

這個效果,和直接從HTTP Request取得byte[],然後執行 (2) Browser_Charset -> Unicode 的效果是一樣的。 

如果在Request裏面設置了CharacterEncoding,那麼POST Data參數就不需要自己手工轉換了,web server的自動轉換就是正確的。URL的參數編碼還涉及到URL編碼,需要考慮的問題多一些,沒有這麼簡單。 

JVM把數據發到瀏覽器的時候。也需要考慮編碼問題。可以在Response裏面設置。另外,HTML Meta Header裏面也可以設置編碼,提醒Browser選擇正確編碼。 

有些語言的VM或者解釋器的字符串編碼可能不同。比如,Ruby。不過,編碼轉換原理都是一樣的。 
發佈了28 篇原創文章 · 獲贊 48 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章