推薦一篇文章,此博客是閱讀這篇文章後自己的一些總結與理解
Unicode
Unicode是一種標準,他收集了世界上所有的字符,併爲每個字符分配了一個唯一的碼點
現在來看看Unicode字符集是長什麼樣子,由於全球所有的字符太多太多,按照字符的類型使用頻率把字符分了17個平面,如圖,每個平面的碼點唯一對應一個字符(當然也有還沒用到的,因爲實際上字符並沒有那麼多),像平面0上的碼點就放着最常用的字符
拿平面0舉例,我們常用的字符 A 就在平面0上,A對應的字符編碼是0041,即圖中平面0的0000-0FFF中的0041,
- 這個0041就是碼點
- 這個0000-10FFFF就是碼點空間
- 0000-10FFFF與全球字符的對應關係就是編碼字符集
專業術語概念
- Coded Character Set(CCS):編碼字符集,將全球的字符收集起來每個分配唯一的字符編號,Unicode字符集就是一種編碼字符集
- Character Encoding Form(CEF):將ccs中的字符編號按照某種規則轉化成二進制序列,UTF8、UTF16就是一種字符編碼表
- Code Point:碼點,即ccs中的字符編號
- Code Unit:代碼單元,已編碼的文本中具有最短bit位的單元,UTF8是8bit長,UTF16是16bit長(至於UTF8爲什麼是8bit,UTF16爲什麼是16bit,後面還會介紹)
- Code Space:碼點空間,所有碼點的集合
- 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唯一表示一個字符。
組合規則如圖:
由於查表麻煩,所以設計了一種算法來根據碼點計算出他對應的高代理低代理
拿編碼點10401舉例:
- 0x10401-0x10000-0x401,
- 0x401轉化爲20位二進制爲 0000 0000 0100 0000 0001
- 一分爲二,x=0000 0000 01 ,y = 00 0000 0001
- H = 0000 0000 01+ 0xD800 == 0000 0000 0000 0001 + 1101 1000 0000 0000 = 1101 1000 0000 0001 = 0xD801
- L = 00 0000 0001+ 0xDC00 == 0000 0000 0000 0001 + 1101 1100 0000 0000 = 1101 1100 0000 0001 = 0xDC01
- UTF16結果: 0xDB01DC01
和UTF16代理對對應
UTF8
UTF8更簡單了,請看圖:
- 首個位爲0,表示這個UTF8是一個字節,他表示的碼點在0000-007F範圍裏,圖中的x位置,用於放置碼點轉成二進制對應的值 (單個字節和ASCII表示的方式一模一樣)
- 首個字節爲1,表示是多個字節,有多少個1表示用了多少個字節表示這個碼點,以0結束
- 如果結構是10…表示他是某個碼點的中部或屁股
- 比如0080用了2個字節,那麼第一個字節是110xxxxx 剩下那個字節10xxxxxx,將0080轉換成二進制爲 0000 0000 1000 0000 ,放入110 00010 10 000000 ,其中斜體部分纔是碼點寸的值