用 Python 理清編碼問題:Unicode萬國碼

Unicode——萬國碼
為解決語言各自為政的編碼,人們提出了Unicode編碼方案,這個(gè)方案簡單粗暴:把世界上所有語言字符統(tǒng)一編碼。Unicode的兩種方案UCS-2和UCS-4,可使用空間分別達(dá)到2^16和2^32個(gè):外星人到訪地球之前,應(yīng)該是夠用的。
我們看幾個(gè)字符的Unicode編碼碼位(code point)是怎樣的:
ls = 'abAB鞏★☆'
print([ord(l) for l in ls])
結(jié)果:[97, 98, 65, 66, 24041, 9733, 9734]。可見,字母abAB的Unicode碼位和其ASCII碼位一致,所以字符為字母時(shí)兩者兼容,而漢字鞏的碼位為24041(0x5de9),與之前的GB系列編碼47534(0xb9ae)不同,所以Unicode和GB系列編碼之間是不完全兼容的:只有ASCII部分兼容。
所有國家的人都使用Unicode編碼之后,擴(kuò)展、亂碼問題都不復(fù)存在:所有人類語言字符都有了一個(gè)統(tǒng)一的編碼碼位,溝通中我們寫出的每個(gè)數(shù)字編碼,都有唯一的字符與他對(duì)應(yīng)。Python中chr函數(shù)返回Unicode碼位對(duì)應(yīng)的字符。
>>> print([chr(i) for i in [123,957,24041]])
['{', 'ν', '鞏']
>>> ls = 'abAB鞏★☆'
>>> ls.encode('Unicode')
Traceback (most recent call last):
File "<stdin>", line 1, in <module> LookupError: unknown encoding: Unicode
UTF-32 四字節(jié)為單位
>>> 'aA鞏'.encode('utf-32LE')
b'a\x00\x00\x00A\x00\x00\x00\xe9\x5d\x00\x00'
UTF-16 兩字節(jié)為單位
>>> 'aA鞏'.encode('utf-16LE')
b'a\x00A\x00\xe9\x5d'
>>> 'aA鞏'.encode('utf-16BE')
b'\x00a\x00A\x5d\xe9'
《格列佛游記》中,小人國國民為吃雞蛋先吃大頭或小頭,針鋒相對(duì),組成了兩個(gè)軍事對(duì)立集團(tuán)big endians和little endians,相互間多次發(fā)動(dòng)戰(zhàn)爭。
UTF-8 變長字節(jié)編碼
>>> 'aA鞏'.encode('utf-8')
b'aA\xe5\xb7\xa9'
UTF-8 編碼轉(zhuǎn)換規(guī)則
0x00-0x7F之間的碼位,兼容ASCII碼,單字節(jié)直接存儲(chǔ)在以下模板 0*** **** 0x80-0x7ff之間,使用兩個(gè)字節(jié)存儲(chǔ),字節(jié)模板是110* **** 10** **** 0x800-0xffff之間,使用三個(gè)字節(jié)存儲(chǔ),字節(jié)模板是1110 **** 10** **** 10** **** 0x10000-0x1fffff之間,使用四個(gè)字節(jié)存儲(chǔ),字節(jié)模板是1111 0*** 10** **** 10** **** 10** ****
UTF三種編碼后的長度
es = 'abcdefghij'
cs = '莫愁前路無知己,天下誰人不識(shí)君。'
codes = ['utf-32le','utf-16le','utf-8']
print([len(es.encode(code)) for code in codes])
print([len(cs.encode(code)) for code in codes])
總結(jié)
Unicode統(tǒng)一了世界各語言字符。Unicode幾種編碼形式中; UTF-32簡單,但浪費(fèi)嚴(yán)重。 UTF-16使用兩個(gè)字節(jié)為單位存儲(chǔ),節(jié)省了空間。 UTF-8使用一個(gè)字節(jié)直接存儲(chǔ),是效率、空間的平衡。
作者:鞏慶奎,大奎,對(duì)計(jì)算機(jī)、電子信息工程感興趣。gongqingkui at 126.com
贊 賞 作 者

更多閱讀
特別推薦

點(diǎn)擊下方閱讀原文加入社區(qū)會(huì)員
評(píng)論
圖片
表情
