Unicode中UTF-8與UTF-16編碼詳解

概述

本文經過介紹Unicode編碼以及對應的兩種編碼方式UTF-8和UTF-16,讓讀者可以瞭解關於字符串編碼的相關知識,同時可以弄清楚Unicode和UTF-8和UTF-16之間的關係。git

本文的主要內容爲:github

  • Unicode編碼,包含Unicode編碼基礎知識以及與UTF-8和UTF-16這兩種編碼方式的關係
  • UTF-8編碼,包含基礎概念和Unicode編碼轉換到UTF-8編碼方式
  • UTF-16編碼,包含基礎概念和Unicode編碼轉換到UTF-16編碼方式
  • JavaScript中string與DOMString

本文做爲utfx.js源碼解析的基礎知識儲備文章,經過了解UTF-8和UTF-16這兩種編碼方式,讀者可以理解使用JavaScript進行編碼轉換的原理。後端

若是想了解編碼轉換的使用場景,能夠閱讀我以前的博客WebSocket系列之JavaScript字符串如何與二進制數據間進行互相轉換源碼分析

若是想了解utfx.js相關的源碼內容,能夠關注個人後續文章。post

Unicode編碼

概念

Unicode(統一碼、萬國碼、單一碼)是計算機科學領域裏的一項業界標準,包括字符集、編碼方案等。Unicode 是爲了解決傳統的字符編碼方案的侷限而產生的,它爲每種語言中的每一個字符設定了統一而且惟一的二進制編碼,以知足跨語言、跨平臺進行文本轉換、處理的要求。1990年開始研發,1994年正式公佈。編碼

一般Unicode編碼是經過2 Byte來表示一個字符的,如U+A12B,2 Byte的二進制表示方法結果就是1010(A)0001(1) 0010(2)1011(B)代理

簡單介紹完了Unicode,咱們來看下UTF-8和UTF-16。須要注意的是:UTF是Unicode TransferFormat的縮寫,UTF-8和UTF-16都是把Unicode碼轉換成程序數據的一種編碼方式。code

UTF-8

概念

UTF-8(8-bit Unicode Transformation Format)是一種針對Unicode的可變長度字符編碼,又稱萬國碼。由Ken Thompson於1992年建立。如今已經標準化爲RFC 3629。UTF-8用1到6個字節編碼Unicode字符。用在網頁上能夠統一頁面顯示中文簡體繁體及其它語言(如英文,日文,韓文)。orm

經過上面的介紹咱們能夠知道,UTF-8是一種很是通用的可變長字符編碼方式。ip

首先,咱們來介紹下什麼叫作可變長編碼?可變長編碼就是指在針對某個字符進行編碼時,他的表示長度是不固定的。像UTF-8裏面,ASCII所表示的字符集就是用1 Byte來表示,而大部分漢字則是用3 Byte來表示。

相較於Unicode統一使用2 Byte來表示字符,在遇到大部分字符均可以用1 Byte表示時,可以節省許多存儲空間。可是,若是遇到須要用超過2 Byte來表示的字符,那麼UTF-8的編碼方式則會消耗更多的存儲空間。

表示方式

經過上面的介紹咱們能夠知道,不一樣的Unicode碼在UTF-8中佔用了不一樣的存儲空間。下面咱們就經過一個表格來看下將Unicode字符轉換爲UTF-8編碼方式的具體步驟。其中的?表示轉換成UTF-8編碼後,Unicode碼佔用的二進制位置。

Unicode碼範圍 UTF-8編碼方式
U+0000~U+007F 0????????
U+0080~U+07FF 110????? 10??????
U+0800~U+FFFF 1110???? 10?????? 10??????
U+10000~U+10FFFF 11110??? 10?????? 10?????? 10??????

當咱們獲得Unicode碼後,咱們先根據上面的這個表判斷其所處的範圍,而後將Unicode碼轉換爲二進制表示,從後往前截取UTF-8編碼中所留爲之長度,從前日後依次填入對應位置,所便可獲得UTF-8的編碼。咱們舉兩個例子來看下:

  • U+0020,這個字符的小於0000 007F,因此只須要用1 Byte來進行編碼。U+0020的二進制表示爲0000(0)0000(0) 0010(2)0000(0),那麼從後往前截取7位獲得010 0000,放入UTF-8編碼方式中,獲得的結果爲00101111,轉換爲十六進制獲得2F。所以存儲在內存中的的順序就是2F
  • U+A12B,這個字符大於0000 0800,小於0000 FFFF,所以須要用3 Byte來進行編碼。U+A12B的二進制表示爲1010(A)0001(1) 0010(2)1011(B)。,那麼從後往前截取16位獲得10100001 00101011(Unicode碼自己),放入UTF-8編碼中,獲得的結果爲11101010 10000100 10101011,轉換十六進制獲得EA84AB。所以,存儲在內存中的順序就是EA 84 AB

經過上面的例子,我相信你們對UTF-8的編碼有了一個深刻的理解。下面,讓咱們來看下另外一種編碼方式——UTF-16。

UTF-16

概念

UTF-16是Unicode字符編碼五層次模型的第三層:字符編碼表(Character Encoding Form,也稱爲 "storage format")的一種實現方式。即把Unicode字符集的抽象碼位映射爲16位長的整數(即碼元, 長度爲2 Byte)的序列,用於數據存儲或傳遞。Unicode字符的碼位,須要1個或者2個16位長的碼元來表示,所以這是一個變長表示。

引用維基百科中對於UTF-16編碼的解釋咱們能夠知道,UTF-16最少也會用2 Byte來表示一個字符,所以沒有辦法兼容ASCII編碼(ASCII編碼使用1 Byte來進行存儲)。

表示方式

在UTF-16中,咱們將Unicode分爲了兩個範圍,分別經過不一樣的方式進行存儲。具體表示見下圖。

Unicode範圍 UTF-16編碼方式
U+000~U+FFFF 2 Byte存儲,編碼後等於Unicode值
U+10000~U+10FFFF 4 Byte存儲,現將Unicode值減去(0x10000),獲得20bit長的值。再將Unicode分爲高10位和低10位。UTF-16編碼的高位是2 Byte,高10位Unicode範圍爲0-0x3FF,將Unicode值加上0XD800,獲得高位代理(或稱爲前導代理,存儲高位);低位也是2 Byte,低十位Unicode範圍同樣爲0~0x3FF,將Unicode值加上0xDC00,獲得低位代理(或稱爲後尾代理,存儲低位)

根據上面的轉換方式,咱們就可以將Unicode碼根據UTF-16的編碼方式進行轉換。下面咱們仍然經過兩個例子來看下:

  • U+0020,這個值的範圍在第一部分,即通過UTF-16編碼後,結果仍然爲U+0020,在內存中的順序爲00 20
  • U+12345, 這個值的範圍在第二部分,所以須要先減去0x10000,獲得0x02345,拆分紅高10位00 0000 1000和低10位11 0100 0101。根據上面規則加上特定值後,高位代理值爲D808,低位代理值爲DF45,最終內存中的順序爲D8 08 DF 45

JavaScript中的string與DOMString

在JavaScript中,全部的string類型(或者被稱爲DOMString)都是使用UTF-16編碼的。

所以,當咱們須要轉換成二進制與後端進行通訊時,須要注意相關的編碼方式。

總結

本文經過對Unicode編碼和UTF-8和UTF-16兩種編碼方式進行介紹,讓你們瞭解Unicode編碼以及相關的兩種程序數據編碼方式。

本文是做爲utfx.js源碼分析的基礎知識儲備文章,在稍後的時間將會給你們帶來相關內容的後續文章——utfx.js源碼解析,讓你們可以瞭解在JavaScript中如何進行相關的編碼轉換。

相關文章
相關標籤/搜索