天天看點

「python」ghost 編碼問題

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