背景
最近在學習和使用python時經常會遇到一些關于字元編碼問題;雖然解決了問題,但是一直沒有認真梳理這方面的知識;是以,這次寫這篇文章整理一下知識點;本文都是通過在網上尋找資料并自己通過代碼驗證,如有錯誤歡迎指正。
環境
python 3.6
基本概念
比特位
二進制的0或1稱為1個bit比特
位元組
8個bit組成1個位元組byte
字元
根據使用的字元編碼方式不同每個字元所占用的位元組數不一樣;
例如,漢字“中”,在gbk字元編碼方式下為2個位元組,而在utf-8字元編碼時為3個位元組
>>> '中'.encode('gbk')
b'\xd6\xd0'
>>> '中'.encode('utf-8')
b'\xe4\xb8\xad'
字元集
字元集(Character set)是多個字元的集合,字元集種類較多,每個字元集包含的字元個數不同,常見字元集名稱:ASCII字元集、GB2312字元集、BIG5字元集、 GB18030字元集、Unicode字元集等。
字元編碼
字元編碼(英語:Character encoding)也稱字集碼,是把字元集中的字元編碼為指定集合中某一對象(例如:比特模式、自然數序列、8位組或者電脈沖),以便文本在計算機中存儲和通過通信網絡的傳遞。
編碼encode
将字元串通過制定的一種字元編碼方式轉換為二進制資料;
>>> a = '中'.encode('gbk')
>>> a
b'\xd6\xd0'
将漢字“中”按照“GBK”字元編碼方式轉換為二進制資料;
解碼decode
将二進制資料通過一種字元編碼方式轉換為字元串;
>>> str(a,'gbk')
'中'
将二進制資料按照“GBK”字元編碼方式轉換為中文字元“中”;
常用字元集
中文GB字元集
GB2312
GB2312對漢字采用雙位元組編碼,收錄7445個圖形字元,其中包括6763個漢字。
>>> a = "中".encode("gb2312")
>>> a
b'\xd6\xd0'
GBK
GBK是對GB2312編碼的擴充,對漢字采用雙位元組編碼。GBK字元集共收錄21003個漢字
>>> a = "中".encode("gbk")
>>> a
b'\xd6\xd0'
可以看到GBK和GB2312編碼得到的二進制資料是相同的,即GBK完全向下相容GB2312;
GB18030
GB18030中收錄27484個漢字。GB18030字元集采用單位元組、雙位元組和四位元組三種方式對字元編碼。相容GBK和GB2312字元集。
>>> a = "中".encode("gb18030")
>>> a
b'\xd6\xd0'
可以看到GB18030和GBK編碼得到的二進制資料是相同的,即GB18030完全向下相容GBK和GB2312;
Unicode字元集
在計算機科學領域中,Unicode(統一碼、萬國碼、單一碼、标準萬國碼)是業界的一種标準,它可以使電腦得以展現世界上數十種文字的系統。Unicode 是基于通用字元集(Universal Character Set)的标準來發展,并且同時也以書本的形式對外發表。Unicode 還不斷在擴增, 每個新版本插入更多新的字元。
Unicode 隻是一個符号集,它隻規定了符号的二進制代碼,卻沒有規定這個二進制代碼應該如何存儲
UTF-32字元編碼
使用4個位元組來存儲Unicode字元;
UTF-16字元編碼
使用2個位元組來存儲Unicode字元;
>>> a = '中'.encode('utf-16')
>>> a
b'\xff\xfe-N'
UTF-8字元編碼
UTF-8使用1~4位元組為每個字元編碼;
1,一個US-ASCIl字元隻需1位元組編碼(Unicode範圍由U+0000~U+007F)。
2,帶有變音符号的拉丁文、希臘文、西裡爾字母、亞美尼亞語、希伯來文、阿拉伯文、叙利亞文等字母則需要2位元組編碼(Unicode範圍由U+0080~U+07FF)。
3,其他語言的字元(包括中日韓文字、東南亞文字、中東文字等)包含了大部分常用字,使用3位元組編碼。
4,其他極少使用的語言字元使用4位元組編碼。
>>> a = '中'.encode('utf-8')
>>> a
b'\xe4\xb8\xad'
字元集轉換
>>> a = '中' # python的字元串類型(str)為unicode字元
>>> b = a.encode('utf-8') # 将變量對應的字元串按照utf-8方式編碼後得到位元組數組b
>>> b
b'\xe4\xb8\xad'
>>> b.decode('utf-8')
'中'
>>> b.decode('utf-8').encode('gbk') # 将位元組數組b按照utf-8解碼然後按照gbk編碼得到其對應的位元組數組
b'\xd6\xd0'
結語
日常開發中經常會遇到字元集的問題;這時需要注意,當我們接收到對方發來的位元組流時我們隻需要将此位元組流采用對方編碼時使用的編碼方式進行解碼,則不會出現亂碼問題。
希望對你有幫助。