Unicode轉換爲UTF-8過程Demo

碎碎念: 這幾天在學習Python對Unicode的支持python

上學的時候,計算機基礎課上總能聽到老師講什麼字節,字符,Unicode,UTF-8吧啦吧啦一堆,反正我是隻記住了名字,至於具體這些名字所表達的含義,當時的我是一點也沒有想要好好了解的意願,必竟是一看就會睡着的內容。數據庫

那時候內心想的是,老師能不能快點講一些能夠「實戰」的東西,這些理論的內容真真太無聊,太無趣了。app

啊啊啊,但是,出來混,果然早晚是要還的,那時候沒聽的講,如今都要本身補回來,QAQ...學習


這篇文章主要是模擬Unicode轉換UTF8編碼的過程,以此來加深對Unicode和UTF8之間關係的理解。測試

首先明確4個基礎概念:編碼

字節: 1字節由8個二進制位組成,是計算機計算存儲容量的一個計量單位(1 Byte=8 bit)code

字符: 1個符號,由1個或多個字節組成orm

Unicode(簡稱UCS ): 編碼規則,爲每種語言中的每一個字符設定了統一而且惟一的二進制編碼。unicode

能夠將Unicode理解成一個字符數據庫,每一個字符都與惟一的數字關聯,稱爲code point。這樣,英文大寫字母A的codepoint是U+0041。而歐元符號的codepoint是U+20A0,其餘相似。一個文本字符串就是這樣一系列的codepoint,表示字符串中每一個字符元素。字符串

UTF-8(Transfer format): Unicode編碼規則的具體實現(將code point轉換到程序數據的編碼方案)

我是這樣理解的:字節:單位名稱,字符:內容呈現,Unicode:制定規則,UTF-8:規則實現

UTF-8最大的一個特色,就是它是一種變長的編碼方式。它可使用1~4個字節表示一個符號,根據不一樣的符號而變化字節長度。

UTF-8的編碼規則很簡單,只有二條:

  • 對於單字節的符號,字節的第一位設爲0,後面7位爲這個符號的unicode碼。所以對於英語字母,UTF-8編碼和ASCII碼是相同的。
  • 對於n字節的符號(n>1),第一個字節的前n位都設爲1,第n+1位設爲0,後面字節的前兩位一概設爲10。剩下的沒有說起的二進制位,所有爲這個符號的unicode碼。 下表總結了編碼規則,字母x表示可用編碼的位。
Unicode符號範圍(16進制) UTF-8編碼方式(2進制)
0000 0000-0000 007F 0xxxxxxx
0000 0080-0000 07FF 110xxxxx 10xxxxxx
0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx
0001 0000-0010 FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

下面,以漢字「嚴」爲例,演示如何實現UTF-8編碼 已知「嚴」的unicode是4E25(100111000100101),根據上表,能夠發現4E25處在第三行的範圍內(0000 0800-0000 FFFF),所以「嚴」的UTF-8編碼須要三個字節,即格式是「1110xxxx 10xxxxxx 10xxxxxx」。

而後,從「嚴」的最後一個二進制位開始,依次從後向前填入格式中的x,多出的位補0。這樣就獲得了,「嚴」的UTF-8編碼是「11100100 10111000 10100101」,轉換成十六進制就是E4B8A5。

腳本主要實現思路

  • 指定一個字符,找到其在Unicode規範中對應的code point。
  • 將code point 轉換爲10進制
  • 根據上一步獲得的10進制數,判斷指定的字符須要使用幾個字節表示
  • 根據Unicode,utf8轉換規則,將步驟2獲得的2進制數經過Utf8編碼方式從新編碼
  • 打印結果(指定字符的utf8編碼)

代碼:

UnicodeSet={"A":"41","嚴":"4E25","漢":"6C49","test":"10ffff"}
utf8Set=[]

test = "嚴"
if test in UnicodeSet:
    # 將code point 轉換爲10進制數字
    
    tencode = int(UnicodeSet[test], base=16)
    twocode = bin(tencode)[2:]

    #判斷測試字符須要幾個字節表示
    if 0<=  tencode <=127:
        codeLevel=1

    elif 128 <= tencode <= 2047:
        codeLevel = 2

    elif 2048 <= tencode <= 65535:
        codeLevel = 3

    elif 65536 <= tencode <=1114111:
        codeLevel = 4
    else:
        print("超出編碼範圍")

    # 按UTF8編碼規則對code point 進行編碼
    if codeLevel == 1:
        rescode = twocode
    else:
        pre = -6
        after = len(twocode)
        for i in range(codeLevel):

            singleByte = "10"+twocode[pre:after]
            pre = pre - 6
            after = after -6
            
            if i == codeLevel-1:
                numzero = 8-codeLevel-len(twocode[0:-after])-1
                singleByte ="1"*codeLevel+"0"+"0"*numzero+twocode[0:-after]
            utf8Set.append(singleByte)
        utf8code = "".join(utf8Set[::-1])
        rescode = hex(int(utf8code,base=2))[2:]

print(f"Unicode定義字符 {test} 的 codepoint爲: {UnicodeSet[test]}\
                                              \n 將codepoint轉換爲utf8編碼:{rescode}")

小白的記錄帖,不足之處,歡迎指出~

歡迎轉載,轉載請註明出處~

相關文章
相關標籤/搜索