1. 程式人生 > >講明白編碼亂碼問題

講明白編碼亂碼問題

在開發的過程中,在處理字串輸入輸出的時候,經常會碰到亂碼的問題。通常的解決方案,在百度或google上查一下,很快就能把問題解決了。對於其原理,並沒有深究。這次,嘗試著把編碼問題理解清楚。

編碼檔案常見的一些詞語有unicode,utf-8,gb2312,ASCII等,這些詞語就是是什麼含義,他們之間又有什麼關係呢?

這需要從計算的發展開始說。

美國人發明了計算機。因為計算機只能處理數字,而人類的自然語言是字元,所以,需要設計一種方案,讓計算機能夠處理字元,於是就出現了編碼。編碼,即約定字元與特定資料的對應關係。例如約定0表示a,1表示b,2表示c,3表示d等等等等,當然,這裡只是舉個栗子,實際計算機中abcd的編碼並不是1234哦。

計算以位元組為基本單位,一個位元組有8位,8位能夠表示256個不同值,也就能編碼256個不同的字元。這對於英語來說,夠用了。英語主要是26個小寫字母,26個大寫字母,再加上9個數字,還有一些括號等號分號等符號,總數也不會超過256,所以,美國人發明了一套編碼規範,在這套規範裡,用一個位元組來對所有字元進行編碼,這套編碼稱為ASCII編碼。

後來計算機技術傳遍了世界。在漢語中,漢字的個數可是遠超256個,使用一個位元組肯定無法編碼所有漢字了。所以就需要更多的位元組,才能編碼全部漢字。使用2個位元組時,最多能編碼65536個字元,這個數量對於常用字來說足夠了。於是中國漢字的這套編碼,稱為GB2312編碼。那麼對於日語,漢語,阿拉伯語,德語呢,各個語言的字元數量不相同,所以,就都設計了自己的編碼規範,於是,計算機世界裡才有了這麼多中編碼。

那為什麼會出現亂碼呢?

因為編碼規範多了,所以,計算機裡的同一個數值,在不同編碼中代表的字元就可能不同,例如48這個值,在ASICC中可能代表c,在gb2312中可能程式碼p,在日語編碼中可能代表t。或者反過來說,同一個字元,在不同編碼中的值是不相同的,比如在ASCII中,m的編碼值為32,在gb2312中,m的編碼值為31,等等。這樣如果用一種編碼方式儲存的字串,讀取時用另一種編碼來讀,讀出來的字串可能就與原來的字串不相同了。這種情況,只是字串變成了另一個字串,還沒有出現亂碼。那麼,再想一步。如果一種編碼的值,在另一種編碼中,根本沒有與該值對應的字元,那麼,這種情況,就出現了亂碼。

亂碼的出現,歸根到底,是不同編碼之間轉換時出現了對應不上的問題。那麼,怎麼解決呢?

後來就提出了unicode,統一編碼,它試圖把全人類的所有的語言的所有字元都編碼進來,使用4個字元,可以編碼65536*65536個字元,約43億個字元,應該夠用了。

unicode編碼雖然大而全,但也有確定,就是它固定佔用4個位元組,比較浪費空間,其實,大多數使用情況涉及到的字元,並沒有那麼多。於是,為了優化unicode,又提出了utf編碼,它使用動態長度的位元組來進行編碼,對於前面的一些字元,只用1個位元組編碼,1個位元組編碼用完了,就用2個位元組編碼後面的字元,等等等等。

This is the end.