簡介
以前一直對(duì)字符編碼很模糊悔据,感覺編碼方式有很多疏橄,在網(wǎng)上查資料也總是看的暈頭轉(zhuǎn)向伟叛,所以在這里先將幾種常見的編碼方式的關(guān)系總結(jié)一下。
常見的字符編碼——ASCII
淤击、Unicode
匠抗、GBK
、UTF-8
-
ASCII
ASCII編碼的全稱是American Standard Code for Information Interchange
污抬,美國信息互換標(biāo)準(zhǔn)代碼汞贸。這是一種最早的、只用來保存英文文字的編碼方式印机。ASCII編碼方式只使用了1個(gè)字節(jié)(8比特位矢腻,可以組合出256種不同的狀態(tài))中0~127種組合存儲(chǔ)了英文的文字。
-
GBK
當(dāng)計(jì)算機(jī)普及到國內(nèi)時(shí)射赛,因?yàn)闈h字的常用字就有將近6000個(gè)多柑,使用ASCII編碼已經(jīng)完全不能滿足使用的需求了。
所以在1981年楣责,國家標(biāo)準(zhǔn)總局發(fā)布了GB2312
(中國國家標(biāo)準(zhǔn)簡體中文字符集)顷蟆,使用2個(gè)字節(jié)的組合,當(dāng)兩個(gè)大于127的字符連在一起時(shí)腐魂,就表示一個(gè)漢字帐偎,這樣就組合出了7000多個(gè)簡體字。
后來因?yàn)闈h字的擴(kuò)展需求蛔屹,發(fā)布了GBK
標(biāo)準(zhǔn)削樊,K
是擴(kuò)展一次漢語拼音的聲母。即不再要求第二個(gè)字節(jié)大于127,只要第一個(gè)字節(jié)大于127漫贞,則表示這是一個(gè)漢字的開始甸箱。這樣共收錄了將近22000個(gè)漢字和符號(hào)。且兼容了GB2312標(biāo)準(zhǔn)迅脐。
2005年時(shí)修訂了GB18030
標(biāo)準(zhǔn)芍殖,支持了國內(nèi)少數(shù)民族的文字,共收錄漢字70000余個(gè)谴蔑。兼容了GBK
標(biāo)準(zhǔn)豌骏。
-
Unicode
就如國內(nèi)定義了GB2312標(biāo)準(zhǔn)一樣,當(dāng)時(shí)各個(gè)國家都規(guī)定了適用于自己語言的一套編碼方式隐锭。但是這就導(dǎo)致各國相互之間誰也不懂誰的編碼窃躲,裝錯(cuò)字符系統(tǒng)就會(huì)導(dǎo)致顯示全是亂碼。
所以這時(shí)ISO(International Standards Organization
钦睡,國際標(biāo)準(zhǔn)化組織)推出了Unicode標(biāo)準(zhǔn)
用以解決這個(gè)問題蒂窒。
Unicode標(biāo)識(shí)以2個(gè)字節(jié)長度的數(shù)字來標(biāo)識(shí)所有字符,除了英文以外的字符全部重新進(jìn)行了統(tǒng)一編碼荞怒。
注意Unicode只是一種標(biāo)準(zhǔn)洒琢,不是編碼方式,給予了每個(gè)字符一個(gè)16比特位的數(shù)字標(biāo)識(shí)褐桌,至于這個(gè)字符在內(nèi)存中是由幾個(gè)字節(jié)存儲(chǔ)纬凤,并不是Unicode標(biāo)準(zhǔn)規(guī)定的。
-
UTF-8
Unicode標(biāo)準(zhǔn)制定后撩嚼,在很長的一段時(shí)間內(nèi)無法推廣,直到互聯(lián)網(wǎng)的普及挖帘,強(qiáng)烈要求出現(xiàn)一種統(tǒng)一的編碼方式完丽。然后就誕生了UTF-8,這個(gè)使用Unicode標(biāo)準(zhǔn)的編碼方式拇舀。
注意:因此逻族,UTF-8是Unicode標(biāo)準(zhǔn)的一種實(shí)現(xiàn)方式。
UTF-8的編碼規(guī)則很簡單骄崩,只有兩條:
- 對(duì)于單字節(jié)的符號(hào)聘鳞,字節(jié)的第一位設(shè)為0,后面7位為這個(gè)符號(hào)的 Unicode 碼要拂。因此對(duì)于英語字母抠璃,UTF-8 編碼和ASCII碼是相同的。
- 對(duì)于n字節(jié)的符號(hào)(n > 1)脱惰,第一個(gè)字節(jié)的前n位都設(shè)為1搏嗡,第n + 1位設(shè)為0,后面字節(jié)的前兩位一律設(shè)為10。剩下的沒有提及的二進(jìn)制位采盒,全部為這個(gè)符號(hào)的 Unicode 碼旧乞。
下表為編碼規(guī)則,字母x
表示可用編碼的位磅氨。
Unicode符號(hào)范圍 | UTF-8編碼方式(二進(jìn)制) |
---|---|
0000 0000-0000 007F | 0xxxxxxx |
0000 0080-0000 07FF | 110xxxxx 10xxxxxx |
0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx |
0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx |
以漢字嚴(yán)
為例尺栖,演示如何實(shí)現(xiàn)UTF-8編碼:
嚴(yán)
的Unicode碼是4E25
(100111000100101
),根據(jù)上表烦租,可以發(fā)現(xiàn)4E25
處在第三行的范圍內(nèi)(0000 0800 - 0000 FFFF
)延赌,因此嚴(yán)
的 UTF-8 編碼需要三個(gè)字節(jié),即格式是1110xxxx 10xxxxxx 10xxxxxx
左权。然后皮胡,從嚴(yán)
的最后一個(gè)二進(jìn)制位開始,依次從后向前填入格式中的x
赏迟,多出的位補(bǔ)0
屡贺。這樣就得到了,嚴(yán)
的 UTF-8 編碼是11100100 10111000 10100101
锌杀,轉(zhuǎn)換成十六進(jìn)制就是E4B8A5
甩栈。
由此可見,漢字的Unicode碼和UTF-8編碼是不同的糕再,它們之間可以通過規(guī)則進(jìn)行轉(zhuǎn)換量没。
注意 : 漢字的Unicode碼是2個(gè)字節(jié),而UTF-8碼是3個(gè)字節(jié)
Python 中的編碼方式轉(zhuǎn)換
Python3中的字符序列類型有兩種:str
和bytes
突想。
bytes對(duì)象是一串十六進(jìn)制格式字符序列殴蹄,如b'\xe6\x88\x91'
,前方的b
標(biāo)示這串字符是bytes對(duì)象猾担。
將bytes對(duì)象通過上述的某種編碼方式可以解析為字符串袭灯,如將b'\xe6\x88\x91'
使用UTF-8編碼方式解碼得到漢字我
,而使用GBK編碼方式解碼無法得到完整的漢字绑嘹。
Python3中使用encode()
和decode()
進(jìn)行字符與二進(jìn)制序列之間的轉(zhuǎn)換稽荧,可以這樣理解:
encode
(編碼)就是把人能看懂的漢字,轉(zhuǎn)換為機(jī)器能看懂的二進(jìn)制序列工腋。
decode
(解碼)就是把人看不懂的二進(jìn)制序列姨丈,轉(zhuǎn)換為漢字。
使用encode()
和decode()
時(shí)擅腰,有個(gè)encoding
參數(shù)蟋恬,默認(rèn)值為UTF-8
,指定了對(duì)字符串進(jìn)行編碼或解碼時(shí)趁冈,使用的編碼方式筋现。
有關(guān)文件的編碼方式
前面說了那么多,還沒有講到有關(guān)文件的編碼方式,而且可能平時(shí)使用open()
打開文件read()
的時(shí)候矾飞,并沒有指定編碼方式一膨,也能夠正常打印出來文件的內(nèi)容。
文件的編碼方式是在open()
是指定的洒沦,有個(gè)encoding
參數(shù)豹绪,作用和字符串解碼一樣,如果以非二進(jìn)制模式(b
)打開文件申眼,會(huì)默認(rèn)通過UTF-8
方式打開瞒津。
所以一份GBK
編碼的文件,如果不以二進(jìn)制模式打開括尸、且不設(shè)置這個(gè)encoding
參數(shù)巷蚪,是會(huì)報(bào)解碼錯(cuò)誤的(UnicodeDecodeError
)。
當(dāng)然濒翻,如果以二進(jìn)制模式打開文件屁柏,再讀取到的文本就已經(jīng)是二進(jìn)制序列了,不涉及encode
問題有送,而是該以什么解碼方式將二進(jìn)制序列轉(zhuǎn)換為人可以讀懂的漢字淌喻。
所以對(duì)于一個(gè)未知編碼方式的文件,如何通過代碼獲取其編碼方式雀摘,然后轉(zhuǎn)換為我們所期望的編碼方式呢裸删?
Python提供了一個(gè)第三方庫chardet
,是char detect
的縮寫阵赠,字符監(jiān)測(cè)涯塔。
將二進(jìn)制序列傳入chardet.detect()
方法,然后會(huì)返回一個(gè)字典清蚀。該字典有3個(gè)鍵值匕荸。
{
'encoding': 'GB2312',
'confidence': 0.99,
'language': 'Chinese'
}
encoding
是所識(shí)別出來該二進(jìn)制序列的編碼方式。
confidence
是所識(shí)別出來的encoding
正確概率(1.0表示100%)轧铁。
language
是該編碼方式適用的語言。
可以根據(jù)confidence
概率決定是否使用encoding
編碼方式旦棉。