UTF8和unicode的轉換

URL Link //n.sfs.tw/15670

2022-03-11 09:54:21 By 張○○

常常看到有些文字會用 0x12AB 或是 0x0123AB、U+4AE0、&#1234 這種形式表示,這種寫法到底是什麼意思?和我們常用的文字之間有什麼關係?

常聽到的 unicode, utf8, ascii 又是什麼?utf8和unicode之間的關係及如何轉換?藉由此文整理並徹底了解。

Unicode

unicode 簡介

計算機起源於美國,上個世紀,他們制定了一套字符編碼規則,稱爲 ASCII 編碼。

ASCII 編碼一共定義了 128 個字符,裡面有英文大小寫數字、標點符號及一些控制用符號,這些字符組成的集合就叫做 ASCII 字符集。

隨着計算機的普及,在不同的地區和國家又出現了很多字符編碼,比如: 大陸的 GB2312、港臺的 BIG5, 日本的 Shift JIS 等等。[1]

但是由於字符編碼不同,文字在不同國家之間經常需要轉換,否則會出現亂碼,網際網路的出現這種情況越來越嚴重需要解決。於是1990開始就有許多機構致力於統一不同的文字編碼,於是 Unicode 就出現了,歷經幾十年的發展,成為現在看到的版本。

簡單來說,unicode 就是把現有的文字符號等加以編碼收集起來,有點類似一本超大字典,所以unicode 也可稱為通用字元集ucs(英語:Universal Character Set, UCS)[3]。

 

unicode的分組

目前的unicode字符分成17組,從U+0000 至 U+10FFFF,每組稱為編碼平面(Code Plane),每平面擁有65536個編碼點。

其中 U+0000 ~ U+FFFF 稱為基本多語言平面(Basic Multilingual Plane,簡記為BMP),也叫做平面0。平面0包含了世界上多種文字。

其餘劃入16個輔助平面(Supplementary Plane),編碼點範圍U+10000 ~ U+10FFFF。

其中平面0的中文字群範圍:

4E00-9FBF:CJK 統一表意符號(CJK Unified Ideographs) 包含漢字

總共有40895-19968= 20927個漢字

其餘分群請看[6]

 

目前的Unicode字符分為17組編排,U+0000 至 U+10FFFF,每組稱為代碼平面(Code Plane),每平面擁有65536(2的16次方)個代碼點。

  • U+0000 ~ U+FFFF劃入基本多語言平面(Basic Multilingual Plane,簡記為BMP),也叫做平面0。平面0包含了世界上多種文字。
  • 其餘劃入16個輔助平面(Supplementary Plane),代碼點範圍U+10000 ~ U+10FFFF。輔助平面中的文字通常使用不上。


原文網址:https://kknews.cc/code/o5jgy8q.html

目前的Unicode字符分為17組編排,U+0000 至 U+10FFFF,每組稱為代碼平面(Code Plane),每平面擁有65536(2的16次方)個代碼點。

  • U+0000 ~ U+FFFF劃入基本多語言平面(Basic Multilingual Plane,簡記為BMP),也叫做平面0。平面0包含了世界上多種文字。
  • 其餘劃入16個輔助平面(Supplementary Plane),代碼點範圍U+10000 ~ U+10FFFF。輔助平面中的文字通常使用不上。


原文網址:https://kknews.cc/code/o5jgy8q.html

目前的Unicode字符分為17組編排,U+0000 至 U+10FFFF,每組稱為代碼平面(Code Plane),每平面擁有65536(2的16次方)個代碼點。

  • U+0000 ~ U+FFFF劃入基本多語言平面(Basic Multilingual Plane,簡記為BMP),也叫做平面0。平面0包含了世界上多種文字。
  • 其餘劃入16個輔助平面(Supplementary Plane),代碼點範圍U+10000 ~ U+10FFFF。輔助平面中的文字通常使用不上。


原文網址:https://kknews.cc/code/o5jgy8q.html

unicode 表示方法

在表示一個Unicode的字元時,通常會用「U+」或小寫的「u+」然後緊接著多組十六進位的數字來表示這一個字元。例如

U+50

U+3105

u+0123AB

程式語言有時會用 0x代替 U+,例如

0x3105

 

網頁上的表示方法

如果想在網頁上呈現unicode,把 'U+' 替換成 '&#',把十六進位的編碼換成十進位,最後在字元的結束加上分號即可,例如顯示注音符號的ㄅ,查碼發現編碼是u+3105,

要把3105換成10進位,即12549,那在網頁上打上

ㄅ

就會出來注音符號的ㄅ。

 

PHP上顯示unicode[4]

print 0x3105;  //12549

json_decode('"\u3105"');  //ㄅ

 

查詢unicode

那要怎麼知道文字的unicode編碼?當然如果可以直接打出來的字不必理會他的編碼,但有些字是以現有的輸入法打不出來的,這時就可以使用查表的方法

可以參考以下網站(2022.3):

unicode有分類清單 https://jicheng.tw/hanzi/unicode?s=9F9C&e=9F9C&font= ;;; (推薦[6])

全字庫 https://www.cns11643.gov.tw/searchQ.jsp?ID=0

unicode清單有轉10進位 https://www.ifreesite.com/unicode/character.htm

 

UTF8

unicode是字元集,要實現的話還是得靠編碼系統,其中有名的有 utf8, utf16, ucs2, ucs4等等。

根據w3tech[5]的研究,到了2022.3,utf8已占了網頁中全部編碼系統的 98%。其餘編碼雖然仍存在諸多系統中,但使用數量已漸漸示微。

 

UTF8的編碼方式

UTF-8是一種非固定長度字節編碼方式。最長可達6個bytes(以下稱為字節)組成一個字,最短只需1個byte。這樣的好處是他相容於ascII的編碼方式。

以下是 UTF-8 的編碼原則(2進位)。

1字節 0xxxxxxx
2字節 110xxxxx 10xxxxxx
3字節 1110xxxx 10xxxxxx 10xxxxxx
4字節 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
5字節 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
6字節 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx

舉例如下,粉底代表定義的指定位元:

A=> 65 => 01000001  <== 等同於ASCII

и=> 208 184 =>  11010000 10111000

錢=>233 140 162 => 11101001 10001100 10100011

ね=>227 129 173  => 11100011 10000001 10101101

一隻豬(請看下圖)=>240,147,131,159  =>11110000 10010011 10000011 10011111

四個字節的字有些電腦無法正確顯示,請參考上圖。

簡單的判斷方法,第一個字節2進位有幾個1開頭就是幾個字節的UTF8字。

 

各字節組擁有的字數

1字節 0xxxxxxx => 2^7= 128個
2字節 110xxxxx 10xxxxxx => 2^(5+6)= 2048
3字節 1110xxxx 10xxxxxx 10xxxxxx => 2^(4+6+6)= 65536
4字節 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx => 2^(3+6+6+6)=2097152
5字節 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx => 67108864
6字節 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx =>2147483648

基本上用3個字節就足以涵蓋67000個字、4個字節就足以涵蓋215萬個字,五個字節以上的字目前沒有。

 

UTF8和unicode 之間的轉換

UTF8是變動字節長,而unicode 是固定字節,這兩者之間如何轉換?

 

unicode轉成 UTF8

Unicode 的字節編碼對照UTF8的編碼方式

直接用範例作說明,例如中文字的「錢」unicode 是 U+9322

1. 因為是9322,屬於平面0 000800~00FFFF這個範圍,也就是三字碼UTF8

2. 9322 => 93 22 (16進位)=> 10010011 00100010 (2進位) => 16個位元拆成 4, 6, 6 分組

  => 10010011 00100010

3. 將分成的3組代換掉 UTF8 的xxxx..

 11101001 10001100 10100010  => 233  140 162  (10進位)

利用PHP來驗證

print chr(233).chr(140).chr(162);

結果

 

UTF8轉成unicode

由UTF8 轉成unicode 只要倒過來運算即可。

以剛才的錢字為例:

1. 取得UTF8 編碼 233 140 162

2. 轉成二進位 11101001 10001100 10100010 

3. 把顏色的部分組合=> 10010011 00100010

4. 8個位元一組轉成16進位=>93 22

5. U+9322完成

 

參考資料

[1] https://www.readfog.com/a/1638084002220969984

[2] https://zh.wikipedia.org/wiki/Unicode

[3] https://zh.wikipedia.org/wiki/%E9%80%9A%E7%94%A8%E5%AD%97%E7%AC%A6%E9%9B%86

[4] https://stackoverflow.com/questions/17539412/print-unicode-characters-php

[5] https://w3techs.com/technologies/cross/character_encoding/ranking

[6] https://jicheng.tw/hanzi/unicode?s=9F9C&e=9F9C&font=