Unicode編碼及其實現:UTF-16、UTF-8,and more

本文主要討論Unicode的編碼與各種實現,著重討論UTF-16,UTF-8的實現規則,以及Big-endian和Little-Endian的存儲規則。


一、Unicode編碼

? ? Unicode出現之前已經有各種編碼標準:ANSI、ISO8859-1、GB2312、GBK以及BIG-5等。Unicode試圖統一各種編碼,在Unicode演進過程中,也有自身不斷修復的過程:剛開始的時候認為16位可以表達65535個字符,已經足夠收集所有的字符;后來隨著大量中文、韓文和日文等表意文字的加入,已經超出了65535個字符,16位已經不能描述所有的字符集了。

? ? 在Unicode字符集中的某個字符對應的代碼值,稱作代碼點(Code Point),用16進制書寫,并加上U+前綴。比如,‘田’的代碼點是U+7530;‘A’的代碼點是U+0041。

? ? 前面說過,Unicode的字符已經超過16位所能表達的范圍,把所有這些CodePoint分成17個代碼平面(Code Plane)

  • U+0000 ~ U+FFFF劃入基本多語言平面(Basic MultilingualPlane,簡記為BMP);
  • 其余劃入16個輔助平面(Supplementary Plane),代碼點范圍U+10000?~ U+10FFFF

? ? 雖然這樣劃分,但并不是每個Plane中的Codepoint都對應有字符,這里面有保留的,還有特殊用途的。


二、Unicode編碼的實現


? ? Unicode的實現方式不同于編碼方式。一個字符的Unicode編碼是確定的,但是在實際存儲和傳輸過程中,由于不同系統平臺的設計不一定一致,以及出于節省空間的目的,對Unicode編碼的實現方式有所不同。Unicode的實現方式稱為Unicode轉換格式(UnicodeTransformation Format,簡稱為UTF)。

? ? 對Unicode編碼的實現方式有UTF-16BE、UTF-16LE、UTF-8、UTF-7以及UTF-32等實現方式,目前通用的實現方式是UTF-16LE、UTF-16BE和UTF-8。


2.1 UTF-16

? ? UTF-16是用16bit編碼來表達Unicode,這樣表達范圍是216(即65536)。如果表達BMP內的字符,用一個UTF-16就可表達,對于輔助平面內的字符,UTF-16有巧妙的設計。

? ? BMP內,從U+D800U+DFFF之間的碼位區段是永久保留不映射到字符, UTF-16利用保留下來的0xD800-0xDFFF區段的碼位來對輔助平面的字符的碼位進行編碼。


對U+0000 ~ U+D7FF以及U+E000 ~ U+FFFF的編碼

? ? UTF-16與UCS-2編碼這個范圍內的碼位為單個16比特長的碼元,數值等價于對應的碼位。BMP中的這些碼位是僅有的碼位可以在UCS-2被表示。

對U+10000 ~ U+10FFFF的編碼

? ? 輔助平面(Supplementary Planes)中的碼位,在UTF-16中被編碼為一對16比特長的碼元(即32bit,4Bytes),稱作代理對(surrogatepair)。


?具體方法是:

UTF-16解碼

hi?\?lo

DC00

DC01

???…???

DFFF

D800

10000

10001

103FF

D801

10400

10401

107FF

???

?

?

?

?

DBFF

10FC00

10FC01

10FFFF

  1. 碼位減去0x10000, 得到的值是長度為20bit(0..0xFFFFF);
  2. 步驟1得到數值的高位的10比特的值(值范圍為0..0x3FF)被加上0xD800得到第一個碼元或稱作高位代理(high surrogate)或前導代理(lead surrogate)。值的范圍是0xD800..0xDBFF
  3. 步驟1得到數值的低位的10比特的值(值范圍為0..0x3FF)被加上0xDC00得到第二個碼元或稱作低位代理(low surrogate)或后尾代理(trail surrogate)。值的范圍是0xDC00..0xDFFF

? ? 這樣,這個范圍內的字符就被編碼成了一個代理對[lead surrogate,trail surrogate]:兩個16bits碼元,取值范圍分別是0xD800..0xDBFF,0xDC00..0xDFF。而BMP中得到的碼元范圍0x0000..0xFFFF中,0xD800..0xDFFF又是保留的,所以這三個區段是相互不重疊的,在解碼時很容易實現。UTF-16解碼高位代理+低位代理得到的碼元與碼位的對應關系如上表所示:

? ? 下面以對U+64321的UTF-16編碼為例,看一下對于輔助平面內的字符的編碼實現:

V? = 0x64321

Vx = V - 0x10000

?? = 0x54321

?? =?01010100 0011 0010 0001

?

Vh =?01 0101 0000?// Vx 的高位部份的 10 bits

Vl =?11 0010 0001?// Vx 的低位部份的 10 bits

w1 = 0xD800 //結果的前16位元初始值

w2 = 0xDC00 //結果的后16位元初始值

?

w1 = w1 | Vh

?? = 1101 1000 0000 0000

?? |???????01 0101 0000

?? = 1101 1001 0101 0000

?? = 0xD950

?

w2 = w2 | Vl

?? = 1101 1100 0000 0000

?? |???????11 0010 0001

?? = 1101 1111 0010 0001

?? = 0xDF21

? ? 所以這個字 U+64321 最后的 UTF-16 編碼是:

0xD950 0xDF21


對于生成的編碼,因為對于16Bits的兩字節,還有存取先后的問題,還有Endian的問題,這在后續講述。


2.2 UTF-8

? ? UTF-8(8-bitUnicode Transformation Format)是一種針對Unicode的可變長度字符編碼,使用一至四個字節為每個字符編碼:

  • ?Unicode范圍為U+0000..U+007F 的128個ASCII字符只需一個字節編碼;
  • ?Unicode范圍為U+0080..U+07FF的字符需要二個字節編碼;
  • ?Unicode范圍為U+0800..U+FFFF的其他BMP中的字符(這包含了大部分常用字)使用三個字節編碼;
  • ?Unicode 輔助平面的字符(其他極少使用的字符)使用四字節編碼。

? ? 對上述提及的第四種字符而言,UTF-8使用四個字節來編碼似乎太耗費資源了。但UTF-8對所有常用的字符都只用三個字節表達,而且UTF-16編碼對前述的第四種字符同樣需要四個字節來編碼,而如果是ASCII居多的字符,UTF-8能極大的節約存儲空間。UTF-8逐漸成為電子郵件、網頁及其他儲存或傳送文字的應用中,優先采用的編碼。互聯網工程工作小組(IETF)要求所有互聯網協議都必須支持UTF-8編碼。互聯網郵件聯盟(IMC)建議所有電子郵件軟件都支持UTF-8編碼。


? ? 對CodePoint各個范圍內的字符進行UTF-8編碼的規則如下:

Code point

UTF-8字節流

U+00000000?– U+0000007F

0xxxxxxx

U+00000080 – U+000007FF

110xxxxx?10xxxxxx

U+00000800 – U+0000FFFF

1110xxxx?10xxxxxx?10xxxxxx

U+00010000 – U+001FFFFF

11110xxx?10xxxxxx?10xxxxxx?10xxxxxx

其中,U+D800到U+DFFF之間的區段在Unicode的定義中沒有具體字符使用的,被用來在UTF-16編碼中對輔助平面的字符進行編碼。


? ? 下面以“田”(CodePoint為U+7530)為例,看如何對其進行UTF-8編碼:

  • ?U+7530落在U+0800..U+FFFF區間,采用三字節編碼;
  • ?0x7530轉換為二進制為111 010100 110000;
  • ?代入表中,得到111001111001010010110000

? ? 這樣,得到“田”(U+7530)的UTF-8編碼:0xE7 94 B0。


? ? 知道UTF-8的編碼規則,我們可以對于UTF-8編碼中的任意字節B,進行下面解碼:

  • ?如果B的第一位為0,則B為ASCII碼,并且B獨立的表示一個字符;如果B的第一位為1,第二位為0,則B為一個非ASCII字符(該字符由多個字節表示)中的一個字節,并且不為字符的第一個字節編碼(字符的第一個字節之外的后編碼);
  • ?如果B的前兩位為1,第三位為0,則B為一個非ASCII字符(該字符由多個字節表示)中的第一個字節,并且該字符由兩個字節表示;
  • ?如果B的前三位為1,第四位為0,則B為一個非ASCII字符(該字符由多個字節表示)中的第一個字節,并且該字符由三個字節表示;
  • ?如果B的前四位為1,第五位為0,則B為一個非ASCII字符(該字符由多個字節表示)中的第一個字節,并且該字符由四個字節表示。

?

2.3 UCS-2 vs UTF-16,UCS-4 vs UTF-32

? ? UCS-2每個字符占用2個字節。UCS-2是UTF-16的子集。在沒有輔助平面前,UTF-16與UCS-2所指的是同一的意思。但當引入輔助平面字符后,UTF-16加入了對輔助平面內的字符的支持。現在若有軟件聲稱自己支持UCS-2編碼,那其實是暗指它不支持UTF-16中超過2bytes的字集。亦即,對于小于0x10000的UCS碼,UTF-16編碼就等于UCS碼。Java早期版本對Unicode的支持,就只是UCS-2的支持,現在加入了對UTF-16的完整支持。

?

? ? UCS-4UTF-32的意義一致,對每個字符都使用4字節(31位字符集,加上恒為0的首位,共需占據32位)。理論上最多能表示231個字符,完全可以涵蓋一切語言所用的符號。雖然每一個碼位使用固定長定的字節看似方便,對于普通只需要2個字節存儲的常用字占絕大對數的字符集來說,卻極大的浪費了空間,并沒怎么得到應用。


三、Big-Endian/Little-Endian與BOM

? ? 在講UTF-16編碼方式時說到,最終生成的編碼可能是2個字節(BMP內的字符),這兩個字節在傳輸和存儲過程中,高/低位位置不同,是不同的字符。比如,“田”的UTF-16編碼是0x7530,但是如果存成0x3075,就變成了“ふ”,另外的字符。

? ? 所以,為了識別一個編碼過的字符的存儲順序,必須用特殊字符來指示。Unicode字符中U+FEFF被用來指示這種存儲順序,被稱作Byte Order Mark(BOM)。

  • ?Big-Endian:最低位地址存放高位字節,可稱高位優先,內存從最低地址開始按順序存放(高數位數字先寫)。最高位字節放最前面。
  • ?Little Endian:最低位地址存放低位字節,可稱低位優先,內存從最低地址開始按順序存放(低數位數字先寫)。最低位字節放最前面。

? ? 所以,BOM在Big-Endian系統上存儲為FE FF;而在Big-Endian系統上存儲則為FF FE。在以Big-Endian存儲的UTF-16(UTF-16BE)的文件的開頭,用FEFF指示;以Little-Endian存儲的UTF-16(UTF-16LE)的文件的開頭,用FEFF指示。

? ? 在Windows的記事本上,另存為的時候,你可以選擇不同的Endian存儲,然后再用純文本編輯工具(Ultra-edit)來檢驗一下,UTF-16的存儲順序。

? ? BOM的UTF-8編碼為11101111?1011101110111111?(EF BB BF),所以一般EF BB BF被放在文本的開頭,用來指示其編碼為UTF-8。


【附】基本概念對照

Code Point碼位

Code Unit碼元是指一個已編碼的文本中具有最短的比特組合的單元。對于UTF-8來說,碼元是8比特長;對于UTF-16來說,碼元是16比特長;對于UTF-32來說,碼元是32比特長。

BMP - Basic Multilingual Plane

UTF - Unicode Transformation Format

BOM – Byte Order Mark

UCS - Universal Character Set

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/452059.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/452059.shtml
英文地址,請注明出處:http://en.pswp.cn/news/452059.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Apache Tiles的使用 前配置

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 使用方法見&#xff1a; http://blog.csdn.net/jiangyu1013/article/details/53161580 1.加maven 依賴&#xff1a; <!-- 頁面布局…

day212223:線程、進程、協程

1、程序工作原理 進程的限制&#xff1a;每一個時刻只能有一個線程來工作。多進程的優點&#xff1a;同時利用多個cpu&#xff0c;能夠同時進行多個操作。缺點&#xff1a;對內存消耗比較高當進程數多于cpu數量的時候會導致不能被調用&#xff0c;進程不是越多越好&#xff0c;…

php課程 8-28 php如何繪制生成顯示圖片

php課程 8-28 php如何繪制生成顯示圖片 一、總結 一句話總結&#xff1a;gd庫輕松解決 1、php圖片操作生成的圖的兩種去向是什么&#xff1f; 一種在頁面直接輸出&#xff0c;一種存進本地磁盤 2、php操作圖片的庫有哪些&#xff1f; PHP: Image Processing and Generation - M…

代碼行技術

用代碼行技術估算軟件規模時&#xff0c;當程序較小時常用的單位是代碼行數&#xff08;LOC&#xff09;&#xff0c;當程序較大時常用的單位是千行代碼數&#xff08;KLOC&#xff09;。 代碼行技術的主要優點是&#xff0c;代碼是所有軟件開發項目都有的“產品”&#xff0c;…

網絡爬蟲--8.編碼趣聞

很久很久以前&#xff0c;有一群人&#xff0c;他們決定用8個可以開合的晶體管來組合成不同的狀態&#xff0c;以表示世界上的萬物。他們看到8個開關狀態是好的&#xff0c;于是他們把這稱為"字節"。 再后來&#xff0c;他們又做了一些可以處理這些字節的機器&#…

科技領域的一分鐘

各位果迷是否能想象在一分鐘之內&#xff0c;科技領域都會發生什么事情&#xff1f;——蘋果平均每分鐘賣出81部 iPad&#xff1b;在 iPhone 4S 發布后的第一個周末&#xff0c;每分鐘賣出925部 iPhone 4S&#xff1b;RIM每分鐘賣出103臺黑莓手機&#xff1b;Amazon每分鐘賣出1…

flavr—超級漂亮的jQuery扁平彈出對話框

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 插件描述&#xff1a;flavr是一個時尚的扁平彈出對話框為您的下一個網站。 flavr是響應設計布局&#xff0c;能夠適應任何屏幕大小。 得…

經緯度之間的距離計算

來自谷歌地圖的計算公式&#xff1a; 通過JAVA的Math類各種方法調用。實現上述公式 private static double EARTH_RADIUS 6378.137;// 單位千米/*** 角度弧度計算公式 rad:(). <br/>* * 360度2π πMath.PI* * x度 x*π/360 弧度* * author chiwei* param d* return* s…

在CentOS7阿里云服務器部署ThinkPHP5,并配置phpstrom實現同步開發(微信小程序及管理員后端)...

小程序和后端同步開發 1.服務器安裝tp5框架&#xff1a; 方法很多比如&#xff1a;github、linux命令直接手動下、composer 都可以&#xff0c;方法很多&#xff0c;百度一下&#xff0c;不再累述 2.這時你會發現怎么都訪問出現不了這個令人舒心的界面&#xff08;ok第一個坑到…

ER圖( 實體聯系圖)

E-R圖也稱實體-聯系圖(Entity Relationship Diagram)&#xff0c;提供了表示實體類型、屬性和聯系的方法&#xff0c;用來描述現實世界的概念模型。 它是描述現實世界概念結構模型的有效方法。是表示概念模型的一種方式&#xff0c;用矩形表示實體型&#xff0c;矩形框內寫明…

網絡爬蟲--9.正則表達式

文章目錄一. 正則表達式1.為什么要學正則表達式2.什么是正則表達式3.正則表達式匹配規則二. Python 的 re 模塊1.re 模塊的一般使用步驟2.compile 函數3.match 方法4.search 方法5.findall 方法6.finditer 方法7.split 方法8.sub 方法9.匹配中文10.貪婪模式與非貪婪模式1&#…

概念模型

將需求分析得到的用戶需求抽象為信息結構&#xff08;即概念模型&#xff09;的過程就是概念結構設計 概念模型的特點 &#xff08;1&#xff09;能真實、充分地反映現實世界&#xff0c;是現實世界的一個真 實模型。 &#xff08;2&#xff09;易于理解&#xff0c;從…

筆記本電池的正確使用方法

一、新買筆記本不需要激活&#xff0c;也不需要前三次的充電12小時深充深放&#xff0c;這主要是鋰電池的原理和特性決定的。電池設計有電量保護&#xff0c;不可能將電量完全用完&#xff0c;當然也不可能過度充電。 二、筆記本電池的壽命受周圍環境的影響很大&#xff0c;最好…

關于XShell 啟動虛擬機的weblogic并在本地打開oracle-weblogic 有關部署

對于沒有用過這款軟件的童鞋&#xff0c;我想必定會有幾步彎路&#xff1a; 1.新建好的虛擬機記得換成root用戶【su root】~ifconfig【eth0 inet addr】如果沒有這項請點擊右上角的電腦標識&#xff0c;鼠標左擊一下連接&#xff0c;沒有了x號就重新輸入ifconfig就有了 2.xshe…

JQuery Datatables Dom 和 Language 參數詳細說明

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 Dom說明 定義表格控件在頁面的顯示順序。 每個控件元素在數據表都有一個關聯的單個字母。 l - 每頁顯示行數的控件f - 檢索條件的控件…

程序員的思維修煉》讀書筆記

PB15061359 王亞正 這本書主要是從思維角度上來寫的&#xff0c;不具體針對到程序員如何寫代碼。我覺得這本書不僅僅適合程序員&#xff0c;其他對各行各業的人都同樣適用。 書中首先講了新手和專家的區別&#xff0c;一個需要靠規則&#xff0c;另一個則是靠感覺。 之后介紹了…

網絡爬蟲--10.使用正則表達式的爬蟲

文章目錄一. 前言二. 第一步&#xff1a;獲取數據三. 第二步&#xff1a;篩選數據四. 第三步&#xff1a;保存數據五. 第四步&#xff1a;實現循環抓取一. 前言 現在擁有了正則表達式這把神兵利器&#xff0c;我們就可以進行對爬取到的全部網頁源代碼進行篩選了。 下面我們一…

一對一 一對多 多對多

一對一 例如&#xff0c;學校里一個班級只有一個正班長&#xff0c;而一個班長只在一個班中任職&#xff0c;則班級與班長之間具有一對一聯系。 一對多 例如&#xff0c;一個班級中有若干名學生&#xff0c;而每個學生只在一個班級中學習&#xff0c;則班級與學生之間具有一…

Mac下的Jenkins安裝

安裝方式 1&#xff09;通過命令行安裝 brew install jenkins&#xff0c;可能會遇到先更新 brew 的情況 https://brew.sh/index_zh-cn&#xff1b; 2&#xff09;通過 pkg 安裝&#xff0c;官方網址&#xff1a;https://jenkins.io/ 安裝完成后&#xff0c;會自動打開瀏覽器…

Order By 排序條件中帶參數的寫法(Oracle數據庫、MyBatis)

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 sortWay 是參數。 當sortWay 為 llpx 就 ORDER BY FORMAT ASC&#xff0c;為 btypx 就ORDER BY BID DESC &#xff0c;為 zhpx 就 ORDE…