刨根究底字符編碼之十二——UTF-8到底是怎麼編碼的 刨根究底字符編碼之十一——UTF-8編碼方式與字節序標記

UTF-8到底是怎麼編碼的

 

1.html

UTF-8編碼是Unicode字符集的一種編碼方式(CEF),其特色是使用變長字節數(即變長碼元序列、變寬碼元序列)來編碼。通常是1到4個字節,固然,也能夠更長。正則表達式

爲何要變長呢?這能夠理解爲按需分配,好比一個字節足以容納全部的ASCII字符,那何須補一堆0用更多的字節來存儲呢?算法

實際上變長編碼有其優點也有其劣勢,優點是節省空間、自動糾錯性能好、利於傳輸、擴展性強,劣勢是不利於程序內部處理,好比正則表達式檢索;而UTF-32這樣等長碼元序列(即等寬碼元序列)的編碼方式就比較適合程序處理,固然,缺點是比較耗費存儲空間。post

 

2.性能

那UTF-8到底是怎麼編碼的呢?也就是說其編碼算法是什麼?編碼

UTF-8編碼最短的爲一個字節、最長的目前爲四個字節,從首字節就能夠判斷一個UTF-8編碼有幾個字節:url

  • 若是首字節以0開頭,確定是單字節編碼(即單個單字節碼元);
  • 若是首字節以110開頭,確定是雙字節編碼(即由兩個單字節碼元所組成的雙碼元序列);
  • 若是首字節以1110開頭,確定是三字節編碼(即由三個單字節碼元所組成的三碼元序列),以此類推。

另外,UTF-8編碼中,除了單字節編碼外,由多個單字節碼元所組成的多字節編碼其首字節之外的後續字節均以10開頭(以區別於單字節編碼以及多字節編碼的首字節)。spa

0、1十、1110以及10至關於UTF-8編碼中各個字節的前綴,所以稱之爲前綴碼。其中,前綴碼1十、1110及10中的0,是前綴碼中的終結標誌。設計

UTF-8編碼中的前綴碼起到了很好的區分和標識的做用——當解碼程序讀取到一個字節的首位爲0,表示這是一個單字節編碼的ASCII字符;當讀取到一個字節的首位爲1,表示這是一個非ASCII字符的多字節編碼字符中的某個字節(多是首字節,也多是後續字節),接下來若繼續讀取到一個1,則肯定爲首字節,再繼續讀取直到碰見終結標誌0爲止,讀取了幾個1,就表示該字符爲幾個字節的編碼;當讀取到一個字節的首位爲1,緊接着讀取到一個終結標誌0,則該字節顯然是非ASCII字符的後續字節(即非首字節)。code

笨笨阿林原創文章,轉載請註明出處)

 

3.

因此,1~4字節的UTF-8編碼看起來分別是這樣的:

                            

單字節可編碼的Unicode碼點值範圍十六進制爲0x0000 ~ 0x007F,十進制爲0 ~ 127;

雙字節可編碼的Unicode碼點值範圍十六進制爲0x0080 ~ 0x07FF,十進制爲128 ~ 2047;

三字節可編碼的Unicode碼點值範圍十六進制爲0x0800 ~ 0xFFFF,十進制爲2048 ~ 65535;

四字節可編碼的Unicode碼點值範圍十六進制爲0x10000 ~ 0x1FFFFF,十進制爲65536 ~ 2097151(目前Unicode字符集碼點編號的最大值爲0x10FFFF,實際還沒有編號到0x1FFFFF;這說明做爲變長字節數的UTF-8編碼其將來擴展性很是強,即使目前的四字節編碼也還有大量編碼空間未被使用,更不論還可擴展爲五字節、六字節……)。

笨笨阿林原創文章,轉載請註明出處)

 

4.

上述Unicode碼點值範圍中十進制值12七、204七、6553五、2097151這幾個臨界值是怎麼來的呢?

由於UTF-8編碼中的每一個字節中都含有起到區分和標識之用的前綴碼0、1十、1110以及10之一,因此1~4個字節的UTF-8編碼其實際有效位數分別爲8-1=7位(2^7-1=127)、16-5=11位(2^11-1=2047)、24-8=16位(2^16-1=65535)、32-11=21位(2^21-1=2097151),以下表所示:

 

注:上圖中的Unicode range即Unicode碼點值範圍(也就是Unicode碼點編號範圍),Hex爲16進制,Binary爲二進制;Encoded bytes即UTF-8編碼中各字節的編碼方式(即編碼算法),其中,x表明Unicode二進制碼點值的單字節低字節中的低7位或8位、y表明兩字節碼點值的高字節中的3位或8位以及三字節碼點值的中字節中的8位、z表明三字節碼點值的高字節中的5位。

所以,UTF-8編碼的算法簡單地用一句話來歸納就是:首先肯定UTF-8編碼中各個字節的前綴碼;以後再將UTF-8編碼中各個字節除了前綴碼所佔用以外的位,依次分配給Unicode字符碼點值二進制中各個位的值,換言之,就是用Unicode字符碼點值二進制中各個位的值,依次填充UTF-8編碼中的各個字節除了前綴碼所佔用以外的位。

 

5.

因爲ASCII字符的UTF-8編碼使用單字節,並且和ASCII編碼如出一轍,這樣全部原先使用ASCII編碼的文檔就能夠直接解碼了,無需進行任何轉換,實現了徹底兼容。考慮到計算機世界中英文文檔的數量之多,這一點意義重大。

而對於其餘非ASCII字符,則使用2~4個字節的編碼來表示。其中,首字節中前置的1的個數表明該字符編碼的字節數(110表明兩個字節、1110表明三個字節,以此類推),非首字節以外的剩餘字節的高2位始終是10,這樣就不會與ASCII字符編碼以及非ASCII字符的首字節編碼相沖突。

例如,假設某個字符的首字節是1110yyyy,前置有三個1,說明該字符編碼總共有三個字節,必須和後面兩個以10開頭的字節結合才能正確解碼該字符。

 

6.

由此可知,UTF-8編碼設計得很是精巧,雖然說不上天衣無縫,但若與後文將要介紹的UTF-1六、UTF-32以及前文介紹過的那些ANSI編碼相比較,對於其精巧設計將體會得更爲深切透徹。所以,UTF-8愈來愈獲得全球一致承認,大有一統字符編碼之勢

笨笨阿林原創文章,轉載請註明出處)

(未完待續)

 

本系列文章上一篇爲:刨根究底字符編碼之十一——UTF-8編碼方式與字節序標記 

預告:本系列文章下一篇將重點介紹UTF-16編碼,敬請關注!】

相關文章
相關標籤/搜索