1. 程式人生 > >常見的字元編碼UTF-8、UTF-16、UTF-32

常見的字元編碼UTF-8、UTF-16、UTF-32

字符集

字符集為每個字元分配了一個唯一的編號,通過這個編號就能找到對應的字元。在程式設計過程中我們經常會使用字元,而使用字元的前提就是把字元放入記憶體中,毫無疑問,放入記憶體中的僅僅是字元的編號,而不是真正的字元實體。

如何才能將字元編號放入記憶體中呢?

對於ASCII字符集,這很容易。ASCII 總共包含 128 個字元,用 7 個位元位(Bit)恰好能夠儲存,不過考慮到計算機一般把位元組(Byte)作為基本單元,為了操作方便,我們不妨用一個位元組(也就是 8 個位元位)來儲存 ASCII。這樣雖然浪費了一個位元位,但是讀寫效率提高了。

但是對於 Unicode,問題就沒有這麼簡單了。Unicode 目前已經包含了上百萬的字元,位置靠前的字元用一個位元組就能儲存,位置靠後的字元用三個位元組才能儲存。我們可以為所有字元都分配三個位元組的記憶體,也可以為編號小的字元分配一個位元組或者兩個位元組的記憶體,而為編號大的字元分配三個位元組的記憶體。

注:Unicode和ASCII 為字符集 注:字符集和字元編碼不是一個概念,字符集定義了文字和二進位制的對應關係,為字元分配了唯一的編號,而字元編碼規定了如何將文字的編號儲存到記憶體中。有的字符集在制定時就考慮到了編碼的問題,是和編碼結合在一起的;有的字符集只管制定字元的編號,至於怎麼編碼,是其他人的事情。

上面的問題有兩個解決方案

1.為每個字元分配固定長度的記憶體 2.為每個字元分配儘量少的記憶體

Unicode 到底使用哪種編碼方案???

Unicode 可以使用的編碼有三種,分別是:

  • UFT-8:一種變長的編碼方案,使用 1~6 個位元組來儲存;
  • UFT-32:一種固定長度的編碼方案,不管字元編號大小,始終使用 4 個位元組來儲存;
  • UTF-16:介於 UTF-8 和 UTF-32 之間,使用 2 個或者 4 個位元組來儲存,長度既固定又可變。 注:UTF 是 Unicode Transformation Format 的縮寫,意思是“Unicode轉換格式”,後面的數字表明至少使用多少個位元位(Bit)來儲存字元。

下面我們介紹著這幾種編碼方式

UTF-8

UTF-8 的編碼規則很簡單:如果只有一個位元組,那麼最高的位元位為 0;如果有多個位元組,那麼第一個位元組從最高位開始,連續有幾個位元位的值為 1,就使用幾個位元組編碼,剩下的位元組均以 10 開頭。 具體的表現形式為:

  • 0xxxxxxx:單位元組編碼形式,這和 ASCII 編碼完全一樣,因此 UTF-8 是相容 ASCII 的;
  • 110xxxxx 10xxxxxx:雙位元組編碼形式;
  • 1110xxxx 10xxxxxx 10xxxxxx:三位元組編碼形式;
  • 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx:四位元組編碼形式。 注:xxx 就用來儲存 Unicode 中的字元編號。

UTF-32

UTF-32 是固定長度的編碼,始終佔用 4 個位元組,足以容納所有的 Unicode 字元,所以直接儲存 Unicode 編號即可,不需要任何編碼轉換。浪費了空間,提高了效率。

UTF-16

UFT-16 比較奇葩,它使用 2 個或者 4 個位元組來儲存。 對於 Unicode 編號範圍在 0 ~ FFFF 之間的字元,UTF-16 使用兩個位元組儲存,並且直接儲存 Unicode 編號,不用進行編碼轉換,這跟 UTF-32 非常類似。 對於 Unicode 編號範圍在 10000~10FFFF 之間的字元,UTF-16 使用四個位元組儲存,具體來說就是:將字元編號的所有位元位分成兩部分,較高的一些位元位用一個值介於 D800~DBFF 之間的雙位元組儲存,較低的一些位元位(剩下的位元位)用一個值介於 DC00~DFFF 之間的雙位元組儲存。

注:只有 UTF-8 相容 ASCII,UTF-32 和 UTF-16 都不相容 ASCII,因為它們沒有單位元組編碼。

GB2312、Shift-JIS 等國家(地區)字符集怎麼編碼

GB2312、GBK、Shift-JIS 等特定國家的字符集都是在 ASCII 的基礎上發展起來的,它們都相容 ASCII,所以只能採用變長的編碼方案:用一個位元組儲存 ASCII 字元,用多個位元組儲存本國字元。

以 GB2312 為例,該字符集收錄的字元較少,所以使用 1~2 個位元組編碼。

  • 對於 ASCII 字元,使用一個位元組儲存,並且該位元組的最高位是 0;
  • 對於中國的字元,使用兩個位元組儲存,並且規定每個位元組的最高位都是 1。 由於單位元組和雙位元組的最高位不一樣,所以很容易區分一個字元到底用了幾個位元組。

寬字元和窄字元(多位元組字元)

有的編碼方式採用 1~n 個位元組儲存,是變長的,例如 UTF-8、GB2312、GBK 等;如果一個字元使用了這種編碼方式,我們就將它稱為多位元組字元,或者窄字元。

有的編碼方式是固定長度的,不管字元編號大小,始終採用 n 個位元組儲存,例如 UTF-32、UTF-16 等;如果一個字元使用了這種編碼方式,我們就將它稱為寬字元。

Unicode 字符集可以使用窄字元的方式儲存,也可以使用寬字元的方式儲存;GB2312、GBK、Shift-JIS 等國家編碼一般都使用窄字元的方式儲存;ASCII 只有一個位元組,無所謂窄字元和寬字元。

本文摘自嚴長生部落格

我的真正身份是改變社會風氣,風靡萬千少女,提高青年人內涵,刺激軟體市場,玉樹臨風的搬磚工?鋼絲球君,英文名字叫Tom Siebel 微信掃碼?可以進行技術交流,歡迎提問!!! GitChat 可在問題下面輸入‘微訊號’,拉你進微信技術交流群