最近編寫自己的rpc小框架,涉及到bytes.這里就想梳理一下編碼與python的字符串和字節碼(bytes)類型.
?
先上個圖,有個印象,隨時可以回頭看.
?
# 前置知識
字符: 在計算機和電信技術中,一個字符是一個單位的字形、類字形單位或符號的基本信息。即一個字符可以是一個中文漢字、一個英文字母、一個阿拉伯數字、一個標點符號等;
字符集: 多個字符的集合。例如GB2312是中國國家標準的簡體中文字符集;
字符編碼:
將某個字符集中的字符轉換成一個唯一編號(碼點,二進制數據).于是同時,我們也可以根據字符編號找到對應字符集中的唯一字符。(專業點的比喻就是映射);
?
UTF 編碼方案:
Unicode字符集轉換格式,即怎樣將Unicode定義的數字轉換成程序數據.
Unicode解決了字符和二進制的對應關系,但是使用unicode表示一個英文字符,太浪費空間。例如:利用unicode表示“Python”需要12個字節才能表示,比原來ASCII表示增加了1倍。
為了解決存儲和網絡傳輸的問題,出現了Unicode Transformation Format,學術名UTF,即:對unicode中的格式進行轉換,以便于在存儲和網絡傳輸時可以節省空間.
同時為了 傳輸時的可靠性 ,從UNICODE到UTF時并不是直接的對應,而是要過一些算法和規則來轉換。
總結:UTF 是為unicode編碼 設計 的一種 在存儲 和傳輸時節省空間的一系列編碼方案。
UCS:
對于Unicode來說,UCS是內碼是唯一編號,而UTF-8則是它的實現方式。
從字符經過字符集得到唯一編號的這個過程.就是USC.
UCS只是規定如何編碼,并沒有規定如何傳輸、保存這個編碼。UCS-2是2個字節保存內碼,UCS-4是4個字節保存內碼.
例如“漢”字的UCS編碼是6C49,我可以用4個ascii數字來傳輸、保存這個編碼;也可以用utf-8編碼:3個連續的字節E6 B1 89來表示它。關鍵在于通信雙方都要認可。UTF-8、UTF-7、UTF-16都是被廣泛接受的方案。UTF-8的一個特別的好處是它與ISO-8859-1完全兼容。UTF是“UCS Transformation Format”的縮寫。
?
位(bit): 數據存儲的最小單位。每個二進制數字0或者1就是1個位; ???? 0或1
字節(byte): 8個位構成一個字節;即:1 byte (字節)= 8 bit(位); ????? 0000,0000~1111,1111
python中的序列操作 : 索引,切片,長度, 組合(序列相加)、重復(乘法),檢查成員,遍歷(迭代),最小值和最大值。
?
# Unicode 是啥
根據前置知識,我們可以猜到.ASCII,Unicode 指的是 字符集+字符編碼的組合.
ASCII字符集:128個 常用英文字符+常用符號
ASCII碼 : 一個字節??? python中: 2個16進制表示此2進制數據 '\xc4\x80'????
Unicode字符集: 萬國碼,所有國家的字符.
Unicode碼 : 兩個字節??? python中: 4個16進制表示此2進制數據 '\u7fd4'????
漢字‘嚴’的 Unicode 是十六進制數4E25,轉換成二進制數足足有15位(100111000100101),也就是說,這個符號的表示至少需要2個字節。表示其他更大的符號,可能需要3個字節或者4個字節,甚至更多。
?
# python3中的字符串
字符串是 Python 中最常用的數據類型。我們可以使用引號(?'?或?"?)來創建字符串。
python3 字符串是一個 Unicode碼點(內碼)組成的不可變序列,支持通用序列操作。可以看作是一個都是數字的元組.這個數字可以在Unicode字符集里找到對應的字符.
在 Python2 中,普通字符串是以1字節ASCII碼進行存儲的,而Unicode字符串則存儲為2字節unicode字符串,這樣能夠表示更多的字符集。使用的語法是在字符串前面加上前綴?u。
?
# UTF-8 又是啥?
字符通過unicode編碼轉成了一個二進制編號數字, 哪怕英文字符也需要2個字節.
而原本ASCII編碼英文字符只需要一個字節.老美老歐不爽了,他們不用,unicode就沒法全球化.
這導致出現了 Unicode 的多種面向傳輸的二進制格式照顧老美老歐的情緒 :
UTF-8( 可變 編碼格式,最為重要),UTF-16,UTF-32編碼.
?
UTF-8:被定義為將代碼點編碼為1至4個字節(其中英文只耗費1個字節,中文3字節),兼容ASCII
UTF-8具體的表現形式為:
- 0xxxxxxx:單字節編碼形式,這和 ASCII 編碼完全一樣,因此 UTF-8 是兼容 ASCII 的;
- 110xxxxx 10xxxxxx:雙字節編碼形式;
- 1110xxxx 10xxxxxx 10xxxxxx:三字節編碼形式;
- 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx:四字節編碼形式。
UTF-16:2個字節
UTF-32:4個字節
注: 值得說明的是,雖然utf編碼對漢字使用3個字節,但即使對于漢字網頁,utf-8編碼也會比unicode編碼節省,因為網頁中包 含了很多的英文字符。
?
# python3中的bytes
bytes對象是一個 0 <= x < 256 區間內的整數(一個字節)不可變序列。
?
# python3 字符串與bytes的區別
可能有人好奇,字符不特么也是二進制嗎,不也是占字節么,python中字符串和bytes連操作都差不多,計算機萬物皆二進制啊.都在扯雞毛蛋呢,把人繞暈了不是.
字符串以,字符為單位進行操作.
bytes由多個字節組成,以字節為單位進行操作。
?
網絡傳輸中在socket這里.是一個字節一個字節讀的.可能讀2個字節才是一個字符.
bytes是面向傳輸的python對象
上面前置知識有一句: 為了傳輸時的可靠性. 可能內碼不方便傳輸?(待續..容我想想.....)
?
# python3 字符串與bytes的轉換
字符串編碼轉成bytes
b = a.encode(encoding='utf-8') # bytes
bytes解碼成字符串
c = b.decode(encoding='utf-8') # str
# 這里可以看出一個漢字 用utf-8編碼是3字節
a = '哈哈'.encode('utf-8')
print(a) # 打印 b'\xe5\x93\x88\xe5\x93\x88'
b = b'\xe5\x93\x88\xe5\x93\x88'.decode('utf-8')
print(b) # 打印 哈哈
?
這里再講一下GBK,為什么GBK看起來能直接編碼呢,它的字符集難道也是UNICODE?
UNICODE 在制訂時沒有考慮與任何一種現有的編碼方案保持兼容,這使得 GBK 與UNICODE 在漢字的內碼編排上完全是不一樣的,沒有一種簡單的算術方法可以把文本內容從UNICODE編碼和另一種編碼進行轉換,這種轉換必須通過 查表 來進行。
如果說unicode編碼成UTF-8是算過去的,unicode編碼成GBK就是一個個找過去的.
unicode碼點〉unicode字符集 〉字符〉GB2312字符集〉GBK碼點
str = "川普牛掰"
str_utf8 = str.encode("UTF-8")
str_gbk = str.encode("GBK")
print(str)
print("UTF-8 編碼:", str_utf8)
print("GBK 編碼:", str_gbk)
print("UTF-8 解碼:", str_utf8.decode('UTF-8', 'strict'))
print("GBK 解碼:", str_gbk.decode('GBK', 'strict'))
》〉》打印〉》〉》
川普牛逼
UTF-8 編碼: b'\xe5\xb7\x9d\xe6\x99\xae\xe7\x89\x9b\xe9\x80\xbc'
GBK 編碼: b'\xb4\xa8\xc6\xd5\xc5\xa3\xb1\xc6'
UTF-8 解碼: 川普牛逼
GBK 解碼: 川普牛逼
》〉》〉》〉》
?
?
?
未完待續,我再想想...
?
?
?
?
?
?
?
?
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
