python3 之 字符串編碼小結(Unicode、utf-8、gbk、gb2312等)


python3 解釋器默認編碼為Unicode,由str類型進行表示。二進制數據使用byte類型表示。

字符串通過編碼轉換成字節串,字節碼通過解碼成為字符串。

encode:str-->bytes

decode:bytes --> str

下面給出一個實例:

 1 mystr = '人生苦短,我學Python'
 2 print('原始字符串mystr:',mystr)      #原始字符串mystr: 人生苦短,我學Python
 3 
 4 
 5 #將字符串進行編碼
 6 mystr_to_utf8 = mystr.encode('utf-8')#默認就是Unicode,不用再decode
 7 mystr_to_gbk = mystr.encode('gbk')
 8 
 9 
10 #打印編碼后的字節串(字面值)
11 print('utf-8編碼后的字節串:',mystr_to_utf8)
12 #utf-8編碼后的字節串: b'\xe4\xba\xba\xe7\x94\x9f\xe8\x8b\xa6\xe7\x9f\xad\xef\xbc\x8c\xe6\x88\x91\xe5\xad\xa6Python'
13 
14 print('gbk編碼后的字節串:',mystr_to_gbk)
15 #gbk編碼后的字節串: b'\xc8\xcb\xc9\xfa\xbf\xe0\xb6\xcc\xa3\xac\xce\xd2\xd1\xa7Python'
16 
17 
18 #正確解碼:
19 print('utf-8解碼mystr_to_utf8:',mystr_to_utf8.decode('utf-8'))    #utf-8解碼mystr_to_utf8: 人生苦短,我學Python
20 print('gbk解碼mystr_to_gbk:',mystr_to_gbk.decode('gbk'))          #gbk解碼mystr_to_gbk: 人生苦短,我學Python
21 
22 
23 #錯誤解碼示范:(會出現報錯信息)
24 print('gbk解碼mystr_to_utf8:',mystr_to_utf8.decode('gbk'))
25 #UnicodeDecodeError: 'gbk' codec can't decode byte 0xa6 in position 20: illegal multibyte sequence
26 
27 print('utf-8解碼mystr_to_gbk:',mystr_to_gbk.decode('utf-8'))

 分析:

  1、python3 內部解釋器默認編碼為Unicode

  2、encode:指明要使用的編碼,decode:指明當前編碼的編碼格式

題外篇:

1、什么是字符編碼

  計算機想要工作必須通電,即用‘電’驅使計算機干活,也就是說‘電’的特性決定了計算機的特性。電的特性即高低電平(人類從邏輯上將二進制數1對應高電平,二進制數0對應低電平),關於磁盤的磁特性也是同樣的道理。結論:計算機只認識數字

很明顯,我們平時在使用計算機時,用的都是人類能讀懂的字符(用高級語言編程的結果也無非是在文件內寫了一堆字符),如何能讓計算機讀懂人類的字符?必須經過一個過程:

  #字符--------(翻譯過程)------->數字 

  #這個過程實際就是一個字符如何對應一個特定數字的標准,這個標准稱之為字符編碼

 2、字符編碼的發展:三個階段

 階段一:

現代計算機起源於美國,最早誕生也是基於英文考慮的ASCII
ASCII:一個Bytes代表一個字符(英文字符/鍵盤上的所有其他字符),1Bytes=8bit,8bit可以表示0-2**8-1種變化,即可以表示256個字符
ASCII最初只用了后七位,127個數字,已經完全能夠代表鍵盤上所有的字符了(英文字符/鍵盤的所有其他字符),后來為了將拉丁文也編碼進了ASCII表,將最高位也占用了

 階段二:

為了滿足中文和英文,中國人定制了GBK
GBK:2Bytes代表一個中文字符,1Bytes表示一個英文字符
為了滿足其他國家,各個國家紛紛定制了自己的編碼
日本把日文編到Shift_JIS里,韓國把韓文編到Euc-kr里

 階段三:

各國有各國的標准,就會不可避免地出現沖突,結果就是,在多語言混合的文本中,顯示出來會有亂碼。如何解決這個問題呢???

說白了亂碼問題的本質就是不統一,如果我們能統一全世界,規定全世界只能使用一種文字符號,然后統一使用一種編碼,那么亂碼問題將不復存在,
ps:就像當年秦始皇統一中國一樣,書同文車同軌,所有的麻煩事全部解決
很明顯,上述的假設是不可能成立的。很多地方或老的系統、應用軟件仍會采用各種各樣的編碼,這是歷史遺留問題。於是我們必須找出一種解決方案或者說編碼方案,需要同時滿足:
1、能夠兼容萬國字符 2、與全世界所有的字符編碼都有映射關系,這樣就可以轉換成任意國家的字符編碼 這就是unicode(定長), 統一用2Bytes代表一個字符, 雖然2**16-1=65535,但unicode卻可以存放100w+個字符,因為unicode存放了與其他編碼的映射關系,准確地說unicode並不是一種嚴格意義上的字符編碼表,下載pdf來查看unicode的詳情: 鏈接:https://pan.baidu.com/s/1dEV3RYp 很明顯對於通篇都是英文的文本來說,unicode的式無疑是多了一倍的存儲空間(二進制最終都是以電或者磁的方式存儲到存儲介質中的) 於是產生了UTF-8(可變長,全稱Unicode Transformation Format),對英文字符只用1Bytes表示,對中文字符用3Bytes,對其他生僻字用更多的Bytes去存 小結內存中統一采用unicode,浪費空間來換取可以轉換成任意編碼(不亂碼),硬盤可以采用各種編碼,如utf-8,保證存放於硬盤或者基於網絡傳輸的數據量很小,提高傳輸效率與穩定性。

總結:

基於目前的現狀,內存中的編碼固定就是unicode,我們唯一可變的就是硬盤的上對應的字符編碼。
此時你可能會覺得,那如果我們以后開發軟時統一都用unicode編碼,那么不就都統一了嗎,關於統一這一點你的思路是沒錯的,但我們不可會使用unicode編碼來編寫程序的文件,因為在通篇都是英文的情況下,耗費的空間幾乎會多出一倍,這樣在軟件讀入內存或寫入磁盤時,都會徒增IO次數,從而降低程序的執行效率。因而我們以后在編寫程序的文件時應該統一使用一個更為精准的字符編碼utf-8(用1Bytes存英文,3Bytes存中文),再次強調,內存中的編碼固定使用unicode。

1、在存入磁盤時,需要將unicode轉成一種更為精准的格式,utf-8:全稱Unicode Transformation Format,將數據量控制到最精簡 2、在讀入內存時,需要將utf-8轉成unicode
所以我們需要明確:內存中用unicode是為了兼容萬國軟件,即便是硬盤中有各國編碼編寫的軟件,unicode也有相對應的映射關系,但在現在的開發中,程序員普遍使用utf-8編碼了,估計在將來的某一天等所有老的軟件都淘汰掉了情況下,就可以變成:內存utf-8<->硬盤utf-8的形式了
 

  

 


免責聲明!

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



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