ghost
參考
Alex-金角大王在知乎上關于python編碼的回答,連結:
https://www.zhihu.com/question/31833164/answer/381137073這一篇總結的标題之是以是「ghost」鬼魂,是因為這個問題就像「ghost」一樣,随時會出現在我的代碼,我的程式中,時不時會冒出來,然後需要解決。
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 0: invalid start byte
UnicodeDecodeError: 'gbk' codec can't decode byte 0x80 in position 205: illegal multibyte sequence"
首先編碼有很多種例如:
- ASCII 占1個位元組,隻支援英文
- GB2312 占2個位元組,支援6700+漢字
- GBK GB2312的更新版,支援21000+漢字
- Shift-JIS 日本字元
- ks_c_5601-1987 南韓編碼
- TIS-620 泰國編碼
雖然每個國家都有自己的編碼,但是這種編碼會有局限性!!!!就是無法對應其他國家的字元。
Unicode編碼出現,Unicode 2-4位元組 已經收錄136690個字元,并還在一直不斷擴張中...
Unicode 起到了2個作用:
- 直接支援全球所有語言,每個國家都可以不用再使用自己之前的舊編碼了,用unicode就可以了。(就跟英語是全球統一語言一樣)
- unicode包含了跟全球所有國家編碼的映射關系(這個很關鍵,就如unicode 知道gbk 編碼是0100101010對應unicode 裡面的啥編碼)
雖然Unicode解決了字元和二進制的對應關系,但是使用unicode表示一個字元,太浪費空間!!!!例如:利用unicode表示“Python”需要12個位元組才能表示,比原來ASCII表示增加了1倍。
為了解決存儲和網絡傳輸的問題,出現了Unicode Transformation Format,學術名UTF,即:對unicode中的進行轉換,以便于在存儲和網絡傳輸時可以節省空間!
UTF-8: 使用1、2、3、4個位元組表示所有字元;優先使用1個字元、無法滿足則使增加一個位元組,最多4個位元組。英文占1個位元組、歐洲語系占2個、東亞占3個,其它及特殊字元占4個
UTF-16: 使用2、4個位元組表示所有字元;優先使用2個位元組,否則使用4個位元組表示。
UTF-32: 使用4個位元組表示所有字元;
總結:UTF 是為unicode編碼 設計 的一種 在存儲 和傳輸時節省空間的編碼方案。
字元在硬碟上的存儲
無論以什麼編碼在記憶體裡顯示字元,存到硬碟上都是2進制。
ascii編碼(美國):
l 0b1101100
o 0b1101111
v 0b1110110
e 0b1100101
GBK編碼(中國):
老 0b11000000 0b11001111
男 0b11000100 0b11010000
孩 0b10111010 0b10100010
Shift_JIS編碼(日本):
私 0b10001110 0b10000100
は 0b10000010 0b11001101
ks_c_5601-1987編碼(南韓):
나 0b10110011 0b10101010
는 0b10110100 0b11000010
TIS-620編碼(泰國):
ฉัน 0b10101001 0b11010001 0b10111001
要注意的是,存到硬碟上時是以何種編碼存的,再從硬碟上讀出來時,就必須以何種編碼讀
編碼的轉換
請問:中國的電腦上有一個檔案用的GBK 編碼,而不是UTF-8,要放在歪果仁的電腦上(沒有GBK編碼)怎麼辦?
兩個對策:
- 讓歪果仁的電腦上都裝上gbk編碼
-
把你的檔案編碼轉成以utf-8編碼
反正這兩種辦法都很費勁
unicode其中一個功能是其包含了跟全球所有國家編碼的映射關系,意思就是,你寫的是gbk的“路飛學城”,但是unicode能自動知道它在unicode中的“路飛學城”的編碼是什麼
Python3的執行過程
python3 執行代碼的過程
- 解釋器找到代碼檔案,把代碼字元串按檔案頭定義的編碼加載到記憶體,轉成unicode
- 把代碼字元串按照文法規則進行解釋,
- 所有的變量字元都會以unicode編碼聲明
UTF-8 --> decode 解碼 --> Unicode
Unicode --> encode 編碼 --> GBK / UTF-8
- decode示例
#在python2中
#_*_coding:utf-8_*_
s = '路飛學城'
print s
s2 = s.decode('utf-8')
print s2
print type(s2)
輸出:
亂碼
路飛學城
unicode
- encode 示例
# 在python2中
#_*_coding:utf-8_*_
s = '路飛學城'
print s
s2 = s.decode('utf-8')
s3 = s2.encode('GBK')
print s3
print type(s3)
亂碼
路飛學城
str
是以
- utf-8可以 decode 解碼成unicode
- unicode 也可以 encode 編碼成 gbk