ASCII 占一個字節,只支持英文
GB2312 占2個字節,只支持6700+漢字
GBK 是GB2312的升級版,支持21000+漢字
Shift-JIS 日本字符編碼
ks_c-5601-1987 韓國字符編碼
TIS-620 泰國編碼
unicode 2-4個字節,兼容萬國編碼,對於漢字收錄136690個,還在增加中...
UTF-8 使用1,2,3,4個字節表示字符
關於unicode萬國字符
1、直接支持全球所有語言,每個國家都可以不再使用自己之前的舊編碼了
2、包含了跟全球所有國家編碼的映射關系
unicode解決了字符和二進制的對應關系,但是使用unicode表示一個字符,太浪費空間(比如表示Python這個單詞,需要12個字節才能表示,比原來ASCII表示增加了一倍的字節)
PS:目前計算機的內存容量普遍都很大,對於內存占用,硬件幾乎不是問題,但是網絡的傳輸是一個非常復雜的環境,局限性比較大,而且網絡傳輸的數據量非常大,如果增加一倍將會可能影響傳輸效率
關於UTF-8
為了解決unicode的缺陷,即存儲過大和網絡傳輸時的問題,出現了UTF-8(Unicode Transformation Format)編碼方案,即unicode中的編碼進行轉換,以便於在存儲和網絡傳輸時可以節省空間
優先使用1個字符,無法滿足再增加一個字符,屬於一種優化機制,最多4個字節(英文占1個字節、歐洲語系占2個字節、東亞占3個字節、其他以及特殊字符占4個字節)
還有UTF-16和UTF-31編碼
UTF-16 使用2、4個字節,優先使用2個字節,否則使用個字節
UTF-32 使用4個字節表示所有字符
PS:UTF是為unicode編碼設計的一種在存儲和傳輸時節省空間的編碼方案
基於目前的現狀,內存中的編碼固定就是unicode(萬國編碼,兼容萬國字符)
在存入磁盤時,需要將unicode轉成一種更為精准的格式,utf-8:全稱Unicode Transformation Format,將數據量控制到最精簡
在讀入內存時,需要將utf-8轉成unicode
PS:所以我們需要明確:內存中用unicode是為了兼容萬國軟件,即便是硬盤中有各國編碼編寫的軟件,unicode也有相對應的映射關系
關於亂碼
存文件時用utf-8編碼,保證兼容萬國,不會亂碼,而讀文件時選擇了錯誤的解碼方式,比如gbk,則在讀階段發生亂碼,讀階段發生亂碼是可以解決的,選對正確的解碼方式就ok了
保證不亂嗎的核心法則就是,字符按照什么標准而編碼的,就要按照什么標准解碼,此處的標准指的就是字符編碼
在內存中寫的所有字符,一視同仁,都是unicode編碼,比如我們打開編輯器,輸入一個“你”,我們並不能說“你”就是一個漢字,此時它僅僅只是一個符號,該符號可能很多國家都在使用,根據我們使用的輸入法不同這個字的樣式可能也不太一樣。只有在我們往硬盤保存或者
基於網絡傳輸時,才能確定”你“到底是一個漢字,還是一個日本字,這就是unicode轉換成其他編碼格式的過程了
PS:存到硬盤上的是什么編碼的文件,再從硬盤上讀取時,就必須以存儲時的編碼標准去讀,不然就亂碼
PS:如果編碼時候的字符是一種國家語言,保存時候用的是不相對應的編碼,如果文檔關閉后,則再打開保存后的文檔就是亂碼,無法修復 *****必須要注意的
python中設定編碼
#coding:utf-8,python中寫在第一行,就是用來決定以什么編碼格式來讀入內存,這一行就是來設定python解釋器這個軟件的編碼使用的編碼格式這個編碼
可以用sys.getdefaultencoding()查看
PS:如果不在python文件指定頭信息#-*-coding:utf-8-*-,那么python2中默認使用ascii,python3中默認使用utf-8
對於print需要特別說明的是:
當程序執行時,比如
x='上' #gbk下,字符串存放為\xc9\xcf
print(x) #這一步是將x指向的那塊新的內存空間(非代碼所在的內存空間)中的內存,打印到終端,按理說應該是存的什么就打印什么,但打印\xc9\xcf,對一些不熟知python編碼的程序員,立馬就懵逼了,所以龜叔自作主張,在print(x)時,使用終端的編碼格式,將內存中的\xc9\xcf轉成字符顯示,此時就需要終端編碼必須為gbk,否則無法正常顯示原內容:上
什么是字符編碼
字符編碼:把字符轉換成(編碼)計算機能識別的數字
解碼:把計算機能識別的數字轉換成人類能識別的字符
在編碼與解碼的過程中一定要遵循一個字符與數字一一對應關系的標准,
該標准稱之為字符編碼表
ASCII:用8bit(1Bytes)表示一個英文字符
1Bytes=8bit
1KB=1024Bytes
1MB=1024KB
1GB=1024MB
1TB=1024GB
1PB=1024TB
GBK:2Bytes表示一個中文字符,1Bytes表示英文字符
unicode: 2Bytes表示一個字符
編碼的轉換
Python3會自動將編碼在內存中轉換成unicode,Python2則不會
Python2中我們將文件頭聲明成UTG-8的編碼,加載到內存並不會像Python3一樣去自動轉換,文件編碼是UTF-8則加載到內存里,變量字符串也是UTF-8,這時候在win系統打開編碼的文件,則是亂碼既然Python2並不會自動把文件編碼轉換成unicode放入內存,那么我們只能自己轉,使用decode(解碼)和encode(編碼)
unicode的二進制------------>encode------------>utf-8格式的二進制(編碼)
unicode的二進制<------------decode------------utf-8格式的二進制(解碼)
例:test.py(沒有解碼直接讀取內存)
#coding: utf-8
s = '中文字符'
print(s)
這時候在CMD窗口下用Python3打開文件是不會亂碼的,因為自動轉換unicode編碼,但是Python2則直接顯示亂碼
PS:讀入內存時候需要解碼(decode),則從內存中讀取保存時候需要編碼(encode)
例:test.py(編碼與編碼之間的轉換)
#coding: utf-8
s = '中文字符' #中文肯定是GBK編碼
s2 = s.decode('utf-8') # 這里將s這個變量解碼成UTF-8
s3 = s2.encode('GBK') #然后將s2編碼成GBK
print(s2)
PS:因此,轉碼的時候一定要先搞明白,字符串str是什么編碼,然后decode成unicode(即UTF-8),然后再encode(編碼)成其他編碼
PS:切記編碼之間不能直接轉,否則亂碼和造成不可逆的文本損壞導致千百萬行代碼損毀
代碼中字符串的默認編碼與代碼文件本身的編碼一致
如:s='中文'
如果是在utf8的文件中,該字符串就是utf8編碼,如果是在gb2312的文件中,則其編碼為gb2312。這種情況下,要進行編碼轉換,都需要先用decode方法將其轉換成unicode編碼,再使用encode方法將其轉換成其他編碼。通常,在沒有指定特定的編碼方式時,都是使用的系統默認編碼創建的代碼文件。
如果字符串是這樣定義:s=u'中文',則該字符串的編碼就被指定為unicode了,即python的內部編碼,而與代碼文件本身的編碼無關。因此,對於這種情況做編碼轉換,只需要直接使用encode方法將其轉換成指定編碼即可。
PS:如果一個字符串已經是unicode了,再進行解碼則將出錯
對其編碼方式是否為unicode進行判斷
isinstance(s,unicode) #用來判斷是否為unicode
用非unicode編碼形式的str來encode會報錯,如何獲得系統的默認編碼?
#!/usr/bin/env python
#coding=utf-8
import sys
printsys.getdefaultencoding()
該段程序在英文WindowsXP上輸出為:ascii
該段程序在英文Windows7上輸出為:mbcs
在某些IDE中,字符串的輸出總是出現亂碼,甚至錯誤,其實是由於IDE的結果輸出控制台自身不能顯示字符串的編碼,而不是程序本身的問題。
如在UliPad中運行如下代碼:
s=u"中文"
print s
會提示:UnicodeEncodeError:'ascii' codec can't encode characters in position 0-1: ordinal notinrange(128)。這是因為UliPad在英文WindowsXP上的控制台信息輸出窗口是按照ascii編碼輸出的(英文系統的默認編碼是ascii),而上面代碼中的字符串是Unicode編碼的,所以輸出時產生了錯誤。
將最后一句改為:prints.encode('GBK')
則能正確輸出“中文”兩個字。
若最后一句改為:prints.encode('utf8')
則輸出:\xe4\xb8\xad\xe6\x96\x87,這是控制台信息輸出窗口按照ascii編碼輸出utf8編碼的字符串的結果。
unicode(str,'gb2312')與str.decode('gb2312')是一樣的,都是將gb2312編碼的str轉為unicode編碼
使用str.__class__可以查看str的編碼形式
注意事項:
1、保證文本文件不亂碼的核心是存取采用同一種編碼標准,就是在什么在編寫的時候是什么語言,就要保存對應的語言標准格式存(如在編寫的時候用的是日文,而保存時候用的是GBK中文編碼,則下次打開時無論用何種編碼都是亂碼無法修復,要特別注意)
2、python3解釋器讀文件默認編碼為utf-8
3、python2解釋器讀文件默認編碼為ASCII
4、#coding:編碼,在文件頭指定編碼的時候,如果打開的是其他編碼的文件,則保存運行時候會亂碼。打開的是什么編碼的文件指定文件頭編碼也需要對應標准
PS:可以指定文件頭來修改解釋器默認讀取文件內容的編碼
bytes類型
bytes類型就是字節類型
把8個二進制一組稱為一個byte,用16進制來表示
Python2里面字符串其實更應該稱為字節串,但是python2里面有一個類型是butes,所以在Python2里面bytes == str(即bytes類型就等於字符串類型)
在Python2里面還有個單獨的類型是unicode,把字符串解碼后,就會變成nuicode
# coding: utf-8
s = '中文字符'
s2 = s.decode('utf-8')
print(type(s2))