Unicode、UTF8、UTF16詳細理解總結

推薦一篇文章,此博客是閱讀這篇文章後自己的一些總結與理解

Unicode

Unicode是一種標準,他收集了世界上所有的字符,併爲每個字符分配了一個唯一的碼點

現在來看看Unicode字符集是長什麼樣子,由於全球所有的字符太多太多,按照字符的類型使用頻率把字符分了17個平面,如圖,每個平面的碼點唯一對應一個字符(當然也有還沒用到的,因爲實際上字符並沒有那麼多),像平面0上的碼點就放着最常用的字符
Unicode 平面分佈和碼點空間
拿平面0舉例,我們常用的字符 A 就在平面0上,A對應的字符編碼是0041,即圖中平面0的0000-0FFF中的0041,

  1. 這個0041就是碼點
  2. 這個0000-10FFFF就是碼點空間
  3. 0000-10FFFF與全球字符的對應關係就是編碼字符集

專業術語概念

  1. Coded Character Set(CCS):編碼字符集,將全球的字符收集起來每個分配唯一的字符編號,Unicode字符集就是一種編碼字符集
  2. Character Encoding Form(CEF):將ccs中的字符編號按照某種規則轉化成二進制序列,UTF8、UTF16就是一種字符編碼表
  3. Code Point:碼點,即ccs中的字符編號
  4. Code Unit:代碼單元,已編碼的文本中具有最短bit位的單元,UTF8是8bit長,UTF16是16bit長(至於UTF8爲什麼是8bit,UTF16爲什麼是16bit,後面還會介紹)
  5. Code Space:碼點空間,所有碼點的集合
  6. BOM(Byte Order Mark):字節序,表示字節的順序,將來怎麼存取轉化後的二進制序列,分爲大頭方式小頭方式

字符編碼表

按照不同的規則將碼點轉換成二進制,像UTF8、UTF16就是不同的規則來轉換碼點

UTF16

最先開始字符還沒收集到那麼多的時候,只有平面0那麼多碼點,所以用的比較粗暴的方式,直接將碼點轉換成二進制(碼點是16進制嘛,直接將它變成二進制),比如000F這個碼點對應的二進制就是0000 0000 0000 1111,這種方式叫UCS-2,用固定的2個字節來表示
後來字符開始變多,平面有17個平面之後,這種方式就表示不了了,於是UTF16就誕生了

UTF16的平面0還是按照UCS02的方法編碼,平面1-17就採用了一個叫代理對的方式。

這裏補充一個知識點,平面0上0xD800~0xDFFF是沒有對應的字符的,也就是這個區間沒有用上,於是UTF16把這區間一分爲二,0xD800~0xDBFF(叫高代理碼點),0xDC00-0xDFFF(叫低代理點),一個高代理和一個低代理組合成的二進制來表示高平面的碼點,即0xD800DC00轉換成的二進制爲1101 1000 0000 0000 1101 1100 0000 0000 來表示碼點10000,這個碼點10000唯一表示一個字符。

組合規則如圖:
UTF-16 代理對
由於查表麻煩,所以設計了一種算法來根據碼點計算出他對應的高代理低代理

增補平面的碼點值減去0x10000
得到的結果轉換爲20位二進制,一分爲二,分爲高10爲x和低十位y
高代理位:H = x + 0xD800,低代理位: L = y + 0xDC00
UTF16編碼結果: HL

拿編碼點10401舉例:

  1. 0x10401-0x10000-0x401,
  2. 0x401轉化爲20位二進制爲 0000 0000 0100 0000 0001
  3. 一分爲二,x=0000 0000 01 ,y = 00 0000 0001
  4. H = 0000 0000 01+ 0xD800 == 0000 0000 0000 0001 + 1101 1000 0000 0000 = 1101 1000 0000 0001 = 0xD801
  5. L = 00 0000 0001+ 0xDC00 == 0000 0000 0000 0001 + 1101 1100 0000 0000 = 1101 1100 0000 0001 = 0xDC01
  6. UTF16結果: 0xDB01DC01

和UTF16代理對對應

UTF8

UTF8更簡單了,請看圖:
UTF-8 編碼方式

  1. 首個位爲0,表示這個UTF8是一個字節,他表示的碼點在0000-007F範圍裏,圖中的x位置,用於放置碼點轉成二進制對應的值 (單個字節和ASCII表示的方式一模一樣)
  2. 首個字節爲1,表示是多個字節,有多少個1表示用了多少個字節表示這個碼點,以0結束
  3. 如果結構是10…表示他是某個碼點的中部或屁股
  4. 比如0080用了2個字節,那麼第一個字節是110xxxxx 剩下那個字節10xxxxxx,將0080轉換成二進制爲 0000 0000 1000 0000 ,放入110 00010 10 000000 ,其中斜體部分纔是碼點寸的值
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章