擼一擼 編碼的問題


不知不覺中這篇文章成了我閱讀量最高的文章。但是感覺自己寫的不是很好。

如果大家感覺對自己幫助不大,可以去看下阮一峰大大的這篇文章:http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html

自始至終都沒有捋一捋關於編碼的問題,偶爾遇到問題就decode,encode解決了。
今天來整理一下關於編碼的問題。如有錯誤還請大家指出。

編碼

  • 系統編碼
    我們都知道計算機存儲信息都是以二進制的形式保存的,而且網絡中信息的傳輸也都是以字節的形式進行傳輸的。那么我們看到漢字,中文都是怎么來的呢?說到這里大家可能想到了ASCII碼表,ASCII碼使用指定的7位或8位二進制數組合來表示128或256種可能的字符。如在ASCII表中 65對應的是字母A,那么某個值為65的字節或者字節串就代表了A。當然英文字母的表現使用一個字節就足夠了,一個字節能表示的字符有256個。但是世界范圍內的字符遠遠不止256個,於是就誕生了GB2312,GBK,unicode多種碼表。其中unicode每個字符使用兩個字節來表示,理論上能表示65536個字符,而且unicode包含各國大多數常用字符,被作為一種國際碼表使用。這個碼表就是系統所使用的碼表。在存儲信息或者讀取信息的時候都是通過碼表來進行的。不同的系統有着不同的默認碼表,
  • Python編輯器編碼
    首先我們在編輯代碼的時候肯定使用的是所在操作系統的碼表。而我們在python文件開頭聲明的#coding=utf-8 是指python在讀取代碼的時候使用utf-8的編碼方式讀取。
    下邊會大概說一下utf-8與unicode的關系。python會有默認的編碼(Python2是ascii,Python3是utf-8),這個默認編碼是指對某個字符處理時使用的編碼格式,但是對於文件讀取,如果不指定編碼格式的話,會使用操作系統默認的編碼格式。

UTF-8 和 unicode的關系

Unicode只是一個符號集,它只規定了符號的二進制代碼,卻沒有規定這個二進制代碼應該如何存儲。

比如,漢字“嚴”的unicode是十六進制數4E25,轉換成二進制數足足有15位(100111000100101),也就是說這個符號的表示至少需要2個字節。
表示其他更大的符號,可能需要3個字節或者4個字節,甚至更多。

這里就有兩個嚴重的問題,第一個問題是,如何才能區別unicode和ascii?計算機怎么知道三個字節表示一個符號,
而不是分別表示三個符號呢?第二個問題是,我們已經知道,英文字母只用一個字節表示就夠了,如果unicode統一規定,
每個符號用三個或四個字節表示,那么每個英文字母前都必然有二到三個字節是0,
這對於存儲來說是極大的浪費,文本文件的大小會因此大出二三倍,這是無法接受的。

它們造成的結果是:
    對於單字節的符號,字節的第一位設為0,后面7位為這個符號的unicode碼。因此對於英語字母,UTF-8編碼和ASCII碼是相同的。
    對於n字節的符號(n>1),第一個字節的前n位都設為1,第n+1位設為0,后面字節的前兩位一律設為10。剩下的沒有提及的二進制位,全部為這個符號的unicode碼。
摘自https://www.cnblogs.com/csguo/p/7402121.html#4532275。

綜上所述 utf-8 是unicode用來表現字符二進制的一種形式。舉個列子
python2下:

#coding=utf-8

s = "小"

print(s.decode(encoding='utf-8'), type(s.decode(encoding='utf-8')))
print(s.decode(encoding='utf-8').encode(encoding='utf-8'), type(s.decode(encoding='utf-8').encode(encoding='utf-8')) )

輸出為:

(u'\u5c0f', <type 'unicode'>)
('\xe5\xb0\x8f', <type 'str'>)

輸出的第一行的u'\u5c0f'十六進制代表十進制數23567。是指unicode碼表中"小"對應的數值為233567,轉化為二進制的形式是 10111000 0001111。

對照 Unicode符號范圍 |UTF-8編碼方式

# 0000 0000-0000 007F | 0xxxxxxx
#
# 0000 0080-0000 07FF | 110xxxxx 10xxxxxx
#
# 0000 0800-0000 FFFF | 1110xxxx 10xxxxxx10xxxxxx
#
# 0001 0000-0010 FFFF | 11110xxx 10xxxxxx10xxxxxx10xxxxxx

5c0f 處於第三欄位,所以UTf-8表現5c0f 需要三個字節。格式轉化的標准為:unicode的兩個字節倒着填進'x'中,按照從后向前的方式。
那么經過轉化,10111000 0001111 ====> 11100101 10110000 10001111 ====> 229 176 143 ====> \xe5\xb0\x8f
與第二行打印的byte符合。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM