使用Python過程中的編碼和解碼

編碼和解碼的問題糾結(jié)了我很久了拘哨,對(duì)他一直只有是是而非的理解,好像是那么回事信峻,但是又不懂倦青,今天終于來認(rèn)真解決一下這個(gè)問題,總結(jié)一下大神們的回答盹舞,做一下筆記产镐。

首先,我們知道踢步,計(jì)算機(jī)中的所有數(shù)據(jù)都以二進(jìn)制存在癣亚,二進(jìn)制的一位有兩種不同的狀態(tài)0和1。一個(gè)字節(jié)(Byte)由8位二進(jìn)制數(shù)組成获印,可以用來表示256種不同的狀態(tài)述雾。將二進(jìn)制序列與字符一一對(duì)應(yīng)的過程就叫做編碼規(guī)則。

一兼丰、ASCII 碼

世界上最著名的編碼規(guī)則是上世紀(jì)60年代美國制定的ASCII 碼玻孟,它將英語字符與二進(jìn)制位之間的關(guān)系做了統(tǒng)一規(guī)定。ASCII 碼規(guī)定一個(gè)字節(jié)的最高位總是0鳍征,用剩余的7位來表示英語中需要的128個(gè)字符(包括不能打出來的32個(gè)控制位)黍翎,比如空格SPACE是32(二進(jìn)制00100000)。

二艳丛、非ASCII編碼

英語用128個(gè)符號(hào)編碼就夠了匣掸,但是用來表示其他語言,128個(gè)符號(hào)是不夠的氮双。

比如旺聚,在法語中,字母上方有注音符號(hào)眶蕉,它就無法用 ASCII 碼表示砰粹。于是,一些歐洲國家就決定,利用字節(jié)中閑置的最高位編入新的符號(hào)碱璃。比如弄痹,法語中的é的編碼為130(二進(jìn)制10000010)。這樣一來嵌器,這些歐洲國家使用的編碼體系肛真,可以表示最多256個(gè)符號(hào)。

但是爽航,這里又出現(xiàn)了新的問題蚓让。不同的國家有不同的字母,因此讥珍,哪怕它們都使用256個(gè)符號(hào)的編碼方式历极,代表的字母卻不一樣。比如衷佃,130在法語編碼中代表了é趟卸,在希伯來語編碼中卻代表了字母Gimel (?),在俄語編碼中又會(huì)代表另一個(gè)符號(hào)氏义。但是不管怎樣锄列,所有這些編碼方式中,0--127表示的符號(hào)是一樣的惯悠,不一樣的只是128--255的這一段邻邮。

至于亞洲國家的文字,使用的符號(hào)就更多了克婶,漢字就多達(dá)10萬左右筒严。一個(gè)字節(jié)只能表示256種符號(hào),肯定是不夠的鸠补,就必須使用多個(gè)字節(jié)表達(dá)一個(gè)符號(hào)萝风。

世界上存在著這么多種類的編碼方式嘀掸,同一個(gè)二進(jìn)制數(shù)字可以被解釋成不同的符號(hào)紫岩。因此,要想打開一個(gè)文本文件睬塌,就必須知道它的編碼方式泉蝌,否則用錯(cuò)誤的編碼方式解讀,就會(huì)出現(xiàn)亂碼揩晴。

如果有一種編碼勋陪,將世界上所有的符號(hào)都納入其中。每一個(gè)符號(hào)都給予一個(gè)獨(dú)一無二的編碼硫兰,就能夠解決文件亂碼的問題诅愚,Unicode應(yīng)運(yùn)而生。

三劫映、Unicode和UTF-8

準(zhǔn)確的說违孝,Unicode不是一種編碼刹前,而是一個(gè)字符集。在Unicode字符集的基礎(chǔ)上產(chǎn)生的UTF-8雌桑、UTF-16和UTF-32才是真正的編碼規(guī)則喇喉。

Unicode字符集

Unicode 當(dāng)然是一個(gè)很大的集合,現(xiàn)在的規(guī)男?樱可以容納100多萬個(gè)符號(hào)拣技。每個(gè)符號(hào)的編碼都不一樣,U+0041表示英語的大寫字母A耍目,U+4E25表示漢字嚴(yán)膏斤。

比如,漢字嚴(yán)的 Unicode 是十六進(jìn)制數(shù)4E25制妄,轉(zhuǎn)換成二進(jìn)制數(shù)足足有15位(100111000100101)掸绞,也就是說,這個(gè)符號(hào)的表示至少需要2個(gè)字節(jié)耕捞。表示其他更大的符號(hào)衔掸,可能需要3個(gè)字節(jié)或者4個(gè)字節(jié),甚至更多俺抽。

這里就有兩個(gè)嚴(yán)重的問題敞映,第一個(gè)問題是,如何才能區(qū)別 Unicode 和 ASCII 磷斧?計(jì)算機(jī)怎么知道三個(gè)字節(jié)表示一個(gè)符號(hào)振愿,而不是分別表示三個(gè)符號(hào)呢?第二個(gè)問題是弛饭,我們已經(jīng)知道冕末,英文字母只用一個(gè)字節(jié)表示就夠了,如果 Unicode 統(tǒng)一規(guī)定侣颂,每個(gè)符號(hào)用三個(gè)或四個(gè)字節(jié)表示档桃,那么每個(gè)英文字母前都必然有二到三個(gè)字節(jié)是0,這對(duì)于存儲(chǔ)來說是極大的浪費(fèi)憔晒,文本文件的大小會(huì)因此大出二三倍藻肄,這是無法接受的。

它們?cè)斐傻慕Y(jié)果是:

  • 出現(xiàn)了 對(duì)應(yīng)Unicode 字符集的多種編碼方式拒担,比如UTF-8嘹屯、UTF-16和UTF-32。
  • Unicode 在很長一段時(shí)間內(nèi)無法推廣从撼,直到互聯(lián)網(wǎng)的出現(xiàn)州弟。
UTF-8

互聯(lián)網(wǎng)的普及,強(qiáng)烈要求出現(xiàn)一種統(tǒng)一的編碼方式。UTF-8 就是在互聯(lián)網(wǎng)上使用最廣的一種 Unicode 的實(shí)現(xiàn)方式婆翔。

UTF-8 最大的一個(gè)特點(diǎn)桐经,就是它是一種變長的編碼方式。它可以使用1~4個(gè)字節(jié)表示一個(gè)符號(hào)浙滤,根據(jù)不同的符號(hào)而變化字節(jié)長度阴挣。
UTF-8 的編碼規(guī)則很簡單,只有二條:

1)對(duì)于單字節(jié)的符號(hào)纺腊,字節(jié)的第一位設(shè)為0畔咧,后面7位為這個(gè)符號(hào)的 Unicode 碼。因此對(duì)于英語字母揖膜,UTF-8 編碼和 ASCII 碼是相同的誓沸。

2)對(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 碼洪添。
下表總結(jié)了編碼規(guī)則,字母x表示可用編碼的位雀费。


Unicode碼位(16進(jìn)制)對(duì)應(yīng)的UTF-8編碼方式

跟據(jù)上表干奢,解讀 UTF-8 編碼非常簡單。如果一個(gè)字節(jié)的第一位是0盏袄,則這個(gè)字節(jié)單獨(dú)就是一個(gè)字符忿峻;如果第一位是1,則連續(xù)有多少個(gè)1辕羽,就表示當(dāng)前字符占用多少個(gè)字節(jié)逛尚。

可以看到,UTF-8是兼容了ASCII碼的一種編碼方式刁愿。

四绰寞、Python中的編解碼

編碼(encode()):將字符轉(zhuǎn)化為計(jì)算機(jī)能夠理解,能夠存儲(chǔ)在內(nèi)存或文件中的二進(jìn)制數(shù)據(jù)酌毡。

如在Python中輸入以下代碼:

str = "簡書"
print(str)
print(type(str))
print(str.encode())
print(type(str.encode()))

輸出:

簡書
<class 'str'>
b'\xe7\xae\x80\xe4\xb9\xa6'
<class 'bytes'>

此過程就是將str類型的數(shù)據(jù)轉(zhuǎn)換為了二進(jìn)制克握,為了方便顯示蕾管,通過16進(jìn)制輸出了編碼后的結(jié)果枷踏。可以看到每個(gè)漢字用了六個(gè)16進(jìn)制數(shù)字來表示掰曾,對(duì)應(yīng)著三位Byte堕仔,三位比特就能表示最多16,777,216個(gè)字符了蚣录,能夠表示完所有漢字捞烟。

python3.6在不指定的情況下傲绣,執(zhí)行編碼方式默認(rèn)使用utf-8編碼,因此在print()打印漢字時(shí)镀梭,不需要再指定encoding = 'utf-8',但在之前的版本需要指定。

注意:python中經(jīng)常需要在方法(或函數(shù))中傳輸參數(shù)(encoding='utf-8')這不一定是在對(duì)數(shù)據(jù)進(jìn)行編碼舌胶,這一點(diǎn)要理解,不然會(huì)感覺很矛盾疮丛。這個(gè)參數(shù)是在告訴方法傳入數(shù)據(jù)的編碼方式為UTF-8(或其他方式)幔嫂,方法才能對(duì)數(shù)據(jù)進(jìn)行正確的解碼。

另一個(gè)使用encoding較多的方法是open誊薄,如下所示:

with open('text.txt','w') as file:
    file.write('簡書')

由于txt文件對(duì)中文的默認(rèn)編碼方式是GBK履恩,Python使用默認(rèn)編碼方式'UTF-8'打開后就是????這樣的亂碼,同時(shí)報(bào)錯(cuò):

File was loaded in the wrong encoding: 'UTF-8'

這時(shí)候通過指定編碼方式就能解決呢蔫,通過'utf-8'方式打開并寫入文件:

with open('text.txt','w',encoding='utf-8') as file:
    file.write('簡書')
解碼(decode()):將二進(jìn)制數(shù)據(jù)轉(zhuǎn)化為能夠閱讀的字符的過程切心。

這個(gè)比較簡單,如上節(jié)通常是指定encoding='utf-8'

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末片吊,一起剝皮案震驚了整個(gè)濱河市绽昏,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌俏脊,老刑警劉巖而涉,帶你破解...
    沈念sama閱讀 218,386評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異联予,居然都是意外死亡啼县,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門沸久,熙熙樓的掌柜王于貴愁眉苦臉地迎上來季眷,“玉大人,你說我怎么就攤上這事卷胯∽庸危” “怎么了?”我有些...
    開封第一講書人閱讀 164,704評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵窑睁,是天一觀的道長挺峡。 經(jīng)常有香客問我,道長担钮,這世上最難降的妖魔是什么橱赠? 我笑而不...
    開封第一講書人閱讀 58,702評(píng)論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮箫津,結(jié)果婚禮上狭姨,老公的妹妹穿的比我還像新娘宰啦。我一直安慰自己,他們只是感情好饼拍,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,716評(píng)論 6 392
  • 文/花漫 我一把揭開白布赡模。 她就那樣靜靜地躺著,像睡著了一般师抄。 火紅的嫁衣襯著肌膚如雪漓柑。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,573評(píng)論 1 305
  • 那天叨吮,我揣著相機(jī)與錄音欺缘,去河邊找鬼。 笑死挤安,一個(gè)胖子當(dāng)著我的面吹牛谚殊,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播蛤铜,決...
    沈念sama閱讀 40,314評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼嫩絮,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了围肥?” 一聲冷哼從身側(cè)響起剿干,我...
    開封第一講書人閱讀 39,230評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎穆刻,沒想到半個(gè)月后置尔,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,680評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡氢伟,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,873評(píng)論 3 336
  • 正文 我和宋清朗相戀三年榜轿,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片朵锣。...
    茶點(diǎn)故事閱讀 39,991評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡谬盐,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出诚些,到底是詐尸還是另有隱情飞傀,我是刑警寧澤,帶...
    沈念sama閱讀 35,706評(píng)論 5 346
  • 正文 年R本政府宣布诬烹,位于F島的核電站砸烦,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏绞吁。R本人自食惡果不足惜幢痘,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,329評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望掀泳。 院中可真熱鬧雪隧,春花似錦、人聲如沸员舵。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,910評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽马僻。三九已至庄拇,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間韭邓,已是汗流浹背措近。 一陣腳步聲響...
    開封第一講書人閱讀 33,038評(píng)論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留女淑,地道東北人瞭郑。 一個(gè)月前我還...
    沈念sama閱讀 48,158評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像鸭你,于是被迫代替她去往敵國和親屈张。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,941評(píng)論 2 355