字符编码表
一、了解字符編碼表
一:計(jì)算機(jī)基礎(chǔ)知識(shí)
1、程序運(yùn)行與三大核心硬件(cpu,內(nèi)存,硬盤(pán))的關(guān)系:
任何一個(gè)程序都是先存放于硬盤(pán)上的,必須先由硬盤(pán)讀取到內(nèi)存,之后cpu去內(nèi)存中取值然后執(zhí)行
2、程序運(yùn)行過(guò)程中產(chǎn)生的數(shù)據(jù)最先放在內(nèi)存中,計(jì)算機(jī)內(nèi)部存取的數(shù)據(jù)用的都是010101010101的二進(jìn)制
二、文本編輯器和python解釋器運(yùn)行原理
python程序運(yùn)行的三個(gè)步驟
python3 D:\a.py
1、先啟動(dòng)python解釋器
2、解釋器會(huì)將a.py的內(nèi)容當(dāng)成普通內(nèi)存從硬盤(pán)讀入內(nèi)存,此時(shí)沒(méi)有語(yǔ)法意義
3、解釋器會(huì)解釋執(zhí)行剛剛讀入內(nèi)存的內(nèi)存,開(kāi)始識(shí)別python語(yǔ)法
任何一個(gè)程序都是先存放于硬盤(pán)上的,必須先由硬盤(pán)讀取到內(nèi)存,之后cpu去內(nèi)存中取值然后執(zhí)行
文本編輯器
1、打開(kāi)編輯器就打開(kāi)了啟動(dòng)了一個(gè)進(jìn)程,是在內(nèi)存中的,所以,用編輯器編寫(xiě)的內(nèi)容也都是存放與內(nèi)存中的,斷電后數(shù)據(jù)丟失
2、要想永久保存,需要點(diǎn)擊保存按鈕:編輯器把內(nèi)存的數(shù)據(jù)刷到了硬盤(pán)上。
3、在我們編寫(xiě)一個(gè)py文件(沒(méi)有執(zhí)行),跟編寫(xiě)其他文件沒(méi)有任何區(qū)別,都只是在編寫(xiě)一堆字符而已。
總結(jié)
相同:1、任何的程序要想運(yùn)行都是先從硬盤(pán)讀取到內(nèi)存
2、文本編輯器和python解釋器都會(huì)去硬盤(pán)中讀取你想要讀取的內(nèi)容
不同:1、文本編輯器將文件內(nèi)容讀取之后僅僅是展示給用戶(hù)看
python解釋器會(huì)識(shí)別語(yǔ)法并解釋執(zhí)行python代碼
三、什么是字符編碼
計(jì)算機(jī)所能識(shí)別的都是二進(jìn)制01010101的數(shù)字,所以總結(jié)計(jì)算機(jī)只能認(rèn)識(shí)數(shù)字
經(jīng)歷的過(guò)程:
字符-----(翻譯過(guò)程)-----數(shù)字
這個(gè)過(guò)程實(shí)際就是一個(gè)字符如何對(duì)應(yīng)一個(gè)特定數(shù)字的標(biāo)準(zhǔn),這個(gè)標(biāo)準(zhǔn)稱(chēng)之為字符編碼
四、字符編碼表發(fā)展史
python 2.x默認(rèn)的字符編碼是ASCII,默認(rèn)的文件編碼也是ASCII。
python 3.x默認(rèn)的字符編碼是unicode,默認(rèn)的文件編碼是utf-8。
1、ASCII:美國(guó)人發(fā)明的最早的只能識(shí)別英文字符
特點(diǎn):采用8bit對(duì)應(yīng)一個(gè)英文字符
8bit=》1Bytes
2、GBK:中國(guó)人發(fā)明的可以識(shí)別中文字符串與英文字符
特點(diǎn):采用16bit對(duì)應(yīng)字符,該字符可以是英文字符、也可以是中文字符
16bit = 》2Bytes
3、shift-JIS日本人發(fā)明的可以識(shí)別日文和英文字符
Euc-kr韓國(guó)人發(fā)明的可以識(shí)別韓文和英文字符
4、unicode:可以識(shí)別萬(wàn)國(guó)字符
特點(diǎn):2Bytes對(duì)應(yīng)一個(gè)字符
在unicode中對(duì)于是英文的文本來(lái)說(shuō),unicode無(wú)疑是多了一倍的存儲(chǔ)空間(二進(jìn)制最終都是以電或者磁的方式存儲(chǔ)到存儲(chǔ)介質(zhì)中的)
于是產(chǎn)生了UTF-8(可變長(zhǎng),全稱(chēng)Unicode Transformation Format),對(duì)英文字符只用1Bytes表示,對(duì)中文字符用3Bytes,對(duì)其他生僻字用更多的Bytes去存
總結(jié):內(nèi)存中統(tǒng)一采用unicode,浪費(fèi)空間來(lái)?yè)Q取可以轉(zhuǎn)換成任意編碼(不亂碼),硬盤(pán)可以采用各種編碼,如utf-8,保證存放于硬盤(pán)或者基于網(wǎng)絡(luò)傳輸?shù)臄?shù)據(jù)量很小,提高傳輸效率與穩(wěn)定性。
字符-----》unicode格式的數(shù)字
GBK shiftJIS**
基于目前的現(xiàn)狀,內(nèi)存中的編碼固定就是unicode,我們唯一可變的就是硬盤(pán)的上對(duì)應(yīng)的字符編碼。
1、
英文字符--------------內(nèi)存:ASCII二進(jìn)制數(shù)--------------->硬盤(pán):ASCII二進(jìn)制數(shù)
中文英文字符--------------內(nèi)存:GBK二進(jìn)制數(shù)--------------->硬盤(pán):GBK二進(jìn)制數(shù)
日文英文字符--------------內(nèi)存:shiftJIS二進(jìn)制數(shù)--------------->硬盤(pán):shiftJIS二進(jìn)制數(shù)
韓文英文字符--------------內(nèi)存:Euc-Kr二進(jìn)制數(shù)--------------->硬盤(pán):Euc-Kr二進(jìn)制數(shù)
2、
中文英文字符------------內(nèi)存:unicode=gbk====>硬盤(pán):GBK二進(jìn)制數(shù)
日文英文字符------------內(nèi)存:unicode=shifJIS>硬盤(pán):shiftJIS二進(jìn)制數(shù)
韓文英文字符------------內(nèi)存:unicode=Euc-Kr=>硬盤(pán):Euc-Kr二進(jìn)制數(shù)
萬(wàn)國(guó)字符----------------內(nèi)存:unicode=utf-8==>硬盤(pán):utf-8二進(jìn)制數(shù)
3、
萬(wàn)國(guó)字符----------------內(nèi)存:unicode=utf-8==>硬盤(pán):utf-8二進(jìn)制數(shù)
萬(wàn)國(guó)字符----------------內(nèi)存:utf-8==========================>硬盤(pán):utf-8二進(jìn)制數(shù)
在讀入內(nèi)存時(shí),需要將utf-8轉(zhuǎn)成unicode
所以我們需要明確:內(nèi)存中用unicode是為了兼容萬(wàn)國(guó)軟件,即便是硬盤(pán)中有各國(guó)編碼編寫(xiě)的軟件,unicode也有相對(duì)應(yīng)的映射關(guān)系,但在現(xiàn)在的開(kāi)發(fā)中,程序員普遍使用utf-8編碼了。
亂碼問(wèn)題
無(wú)論以什么編碼在內(nèi)存里顯示字符,存到硬盤(pán)上都是二進(jìn)制,所以編碼不對(duì),程序就會(huì)出錯(cuò)。
1、存的時(shí)候亂了:采用的字符編碼表無(wú)法識(shí)別輸入的字符
存的時(shí)候就已經(jīng)亂了,是無(wú)法補(bǔ)救的,取的時(shí)候一定也亂了
解決方法:存入硬盤(pán)的編碼格式應(yīng)該用utf-8格式
2、存的時(shí)候沒(méi)有亂碼:采用的字符編碼表可以識(shí)別輸入的字符
但是取的時(shí)候亂碼了:采用的字符編碼表與當(dāng)初存的時(shí)候用的不是同一張表
解決方法:存的時(shí)候用什么編碼,取的時(shí)候一定要用同樣的編碼格式
與運(yùn)行python程序有關(guān)的亂碼問(wèn)題:
1、保證運(yùn)行python程序的前兩個(gè)階段不亂碼
在python文件的開(kāi)頭加一行:
#coding:文件存的時(shí)候用的編碼格式
python2.x的bytes與python3.x的bytes的區(qū)別
Python2將string處理為原生的bytes類(lèi)型,而不是 unicode。而Python3所有的 string均是unicode類(lèi)型。
在python2.x中,寫(xiě)字符串,比如
s = ”學(xué)習(xí)“
print s
學(xué)習(xí)
s # 字節(jié)類(lèi)型
‘\xd1\xa7\xcf\xb0’
雖然說(shuō)打印的是中文學(xué)習(xí),但是直接調(diào)用變量s時(shí),顯示的卻是一個(gè)個(gè)16進(jìn)制表示的二進(jìn)制字節(jié),我們稱(chēng)這個(gè)為byte類(lèi)型,即字節(jié)類(lèi)型,它把8個(gè)二進(jìn)制組成一個(gè)byte,用16進(jìn)制表示。
所以說(shuō)python2.x的字符串其實(shí)更應(yīng)該稱(chēng)為字符串,通過(guò)存儲(chǔ)的方式就能看出來(lái),但是在python2.x中還有一個(gè)bytes類(lèi)型,兩個(gè)是否相同呢,回答是肯定的,在python2.x中,bytes==str。
python3.x中,把字符串變成了unicode,文件默認(rèn)編碼為utf-8。這意味著,只要用python3.x,無(wú)論我們的程序以那種語(yǔ)言開(kāi)發(fā),都可以在全球各國(guó)電腦上正常顯示。
python3.x除了把字符串的編碼改成了unicode,還把str和bytes做了明確區(qū)分,str就是unicode格式的字符串,而bytes就是單純的二進(jìn)制。(補(bǔ)充一個(gè)問(wèn)題,在python3.x中,只要把unicode編碼,字符串就會(huì)變成了bytes格式,也不直接打印成gbk的字符,我覺(jué)得就是想通過(guò)這樣的方式明確的告訴你,想在python3.x中看字符串,必須是unicode,其他編碼一律是bytes格式)。
深入中文編碼問(wèn)題
python3內(nèi)部使用的是unicode編碼,而外部卻要面對(duì)千奇百怪的各種編碼,比如作為中國(guó)程序經(jīng)常要面對(duì)的gbk,gb2312,utf8等,那這些編碼是怎么轉(zhuǎn)換成內(nèi)部的unicode呢?
首先看一下源代碼文件中使用字符串的情況。源代碼文件作為文本文件就必然是以某種編碼形式存儲(chǔ)代碼的,python2默認(rèn)源代碼文件是asci編碼,python3默認(rèn)源代碼文件是utf-8編碼。比如給python2代碼文件中的一個(gè)變量賦值:
s1 = ‘a(chǎn)’
print s1
python2認(rèn)為這個(gè)字符’a’就是一個(gè)asci編碼的字符,這個(gè)文件可以正常執(zhí)行,并打印出’a’字符。在僅僅使用英文字符的情況下一切正常,但是如果用了中文,比如:
s1 = ‘哈哈’
print s1
這個(gè)代碼文件被執(zhí)行時(shí)就會(huì)出錯(cuò),就是編碼出了問(wèn)題。python2默認(rèn)將代碼文件內(nèi)容當(dāng)作asci編碼處理,但asci編碼中不存在中文,因此拋出異常。
解決問(wèn)題之道就是要讓python2解釋器知道文件中使用的是什么編碼形式,對(duì)于中文,可以用的常見(jiàn)編碼有utf-8,gbk和gb2312等。只需在代碼文件的最前端添加如下:
# -- coding: utf-8 --
這就是告知python2解釋器,這個(gè)文件里的文本是用utf-8編碼的。這樣,python就會(huì)依照utf-8的編碼形式解讀其中的字符,然后轉(zhuǎn)換成unicode編碼內(nèi)部處理使用。
不過(guò),如果你在Windows控制臺(tái)下運(yùn)行此代碼的話(huà),雖然程序是執(zhí)行了,但屏幕上打印出的卻不是哈哈字。這是由于python2編碼與控制臺(tái)編碼的不一致造成的。Windows下控制臺(tái)中的編碼使用的是gbk,而在代碼中使用的utf-8,python2按照utf-8編碼打印到gbk編碼的控制臺(tái)下自然就會(huì)不一致而不能打印出正確的漢字。
解決辦法一個(gè)是將源代碼的編碼也改成gbk,也就是代碼第一行改成:
# -- coding: gbk --
另一種方法是保持源碼文件的utf-8不變,而是在’哈哈’前面加個(gè)u字,也就是:
s1=u’哈哈’
print s1
這樣就可以正確打印出’哈哈’字了。這里的這個(gè)u表示將后面跟的字符串以u(píng)nicode格式存儲(chǔ)。python2會(huì)根據(jù)代碼第一行標(biāo)稱(chēng)的utf-8編碼,識(shí)別代碼中的漢字’哈哈’,然后轉(zhuǎn)換成unicode對(duì)象。如果我們用type查看一下’哈哈’的數(shù)據(jù)類(lèi)型type(‘哈哈’),會(huì)得到<type ‘str’>,而type(u’哈哈’),則會(huì)得到<type ‘unicode’>。
type(‘哈哈’)
<type ‘str’>
type(u’哈哈’)
<type ‘unicode’>
也就是在字符前面加u就表明這是一個(gè)unicode對(duì)象,這個(gè)字會(huì)以u(píng)nicode格式存在于內(nèi)存中,而如果不加u,表明這僅僅是一個(gè)使用某種編碼的字符串,編碼格式取決于python2對(duì)源碼文件編碼的識(shí)別,這里就是utf-8。
Python2在向控制臺(tái)輸出unicode對(duì)象的時(shí)候會(huì)自動(dòng)根據(jù)輸出環(huán)境的編碼進(jìn)行轉(zhuǎn)換,但如果輸出的不是unicode對(duì)象而是普通字符串,則會(huì)直接按照字符串的編碼輸出字符串,從而出現(xiàn)上面的現(xiàn)象。
使用unicode對(duì)象的話(huà),除了這樣使用u標(biāo)記,還可以使用unicode類(lèi)以及字符串的encode和decode方法。
unicode類(lèi)的構(gòu)造函數(shù)接受一個(gè)字符串參數(shù)和一個(gè)編碼參數(shù),將字符串封裝為一個(gè)unicode,比如在這里,由于我們用的是utf-8編碼,所以u(píng)nicode中的編碼參數(shù)使用’utf-8’,將字符封裝為unicode對(duì)象,然后正確輸出到控制臺(tái):
s1=unicode(‘哈’, ‘utf-8′)
print s1
另外,用decode函數(shù)也可以將一個(gè)普通字符串轉(zhuǎn)換為unicode對(duì)象。很多人都搞不明白python2字符串的decode和encode函數(shù)都是什么意思。這里簡(jiǎn)要說(shuō)明一下。
decode函數(shù)是將普通字符串按照參數(shù)中的編碼格式進(jìn)行解析,然后生成對(duì)應(yīng)的unicode對(duì)象,比如在這里我們代碼用的是utf-8,那么把一個(gè)字符串轉(zhuǎn)換為unicode對(duì)象就是如下形式:
s2 = ‘哈哈’.decode(‘utf-8’)
type(s2)
<type ‘unicode’>
這時(shí),s2就是一個(gè)存儲(chǔ)了’哈哈’字符串的unicode對(duì)象,其實(shí)就和unicode(‘哈哈’, ‘utf-8′)以及u’哈哈’是相同的。
encode函數(shù)正好就是相反的功能,是將一個(gè)unicode對(duì)象轉(zhuǎn)換為參數(shù)中編碼格式的普通字符串,比如下面代碼:
復(fù)制代碼
s3 = unicode(‘哈哈’, ‘utf-8’).encode(‘utf-8’)
type(s3)
<type ‘str’>
或者:
s3 = ‘哈哈’.decode(‘utf-8’).encode(‘utf-8’)
type(s3)
<type ‘str’>
復(fù)制代碼
s3現(xiàn)在又變回了utf-8的’哈哈’。同樣的,也可指定其它編碼格式,但要注意的是,用什么格式編碼,就用什么格式解碼,否則會(huì)出現(xiàn)中文亂碼問(wèn)題。
字符編碼
目前使用的編碼方式有:ASCII碼(一個(gè)字節(jié))、Unicode碼(兩個(gè)字節(jié))、UTF-8碼(可變長(zhǎng)的編碼)。我們已經(jīng)知道了,字符串也是一種數(shù)據(jù)類(lèi)型,但是,字符串比較特殊的是還有一個(gè)編碼問(wèn)題。
因?yàn)橛?jì)算機(jī)只能處理數(shù)字,如果要處理文本,就必須先把文本轉(zhuǎn)換為數(shù)字才能處理。最早的計(jì)算機(jī)在設(shè)計(jì)時(shí)采用8個(gè)比特(bit)作為一個(gè)字節(jié)(byte),所以,一個(gè)字節(jié)能表示的最大的整數(shù)就是255(二進(jìn)制11111111=十進(jìn)制255),如果要表示更大的整數(shù),就必須用更多的字節(jié)。比如兩個(gè)字節(jié)可以表示的最大整數(shù)是65535,4個(gè)字節(jié)可以表示的最大整數(shù)是4294967295。
由于計(jì)算機(jī)是美國(guó)人發(fā)明的,因此,最早只有127個(gè)字符被編碼到計(jì)算機(jī)里,也就是大小寫(xiě)英文字母、數(shù)字和一些符號(hào),這個(gè)編碼表被稱(chēng)為ASCII編碼,比如大寫(xiě)字母A的編碼是65,小寫(xiě)字母z的編碼是122。但是要處理中文顯然一個(gè)字節(jié)是不夠的,至少需要兩個(gè)字節(jié),而且還不能和ASCII編碼沖突,所以,中國(guó)制定了GB2312編碼,用來(lái)把中文編進(jìn)去。可以想得到的是,全世界有上百種語(yǔ)言,日本把日文編到Shift_JIS里,韓國(guó)把韓文編到Euc-kr里,各國(guó)有各國(guó)的標(biāo)準(zhǔn),就會(huì)不可避免地出現(xiàn)沖突,結(jié)果就是,在多語(yǔ)言混合的文本中,顯示出來(lái)會(huì)有亂碼。因此,Unicode應(yīng)運(yùn)而生。Unicode把所有語(yǔ)言都統(tǒng)一到一套編碼里,這樣就不會(huì)再有亂碼問(wèn)題了。Unicode標(biāo)準(zhǔn)也在不斷發(fā)展,但最常用的是用兩個(gè)字節(jié)表示一個(gè)字符(如果要用到非常偏僻的字符,就需要4個(gè)字節(jié))。現(xiàn)代操作系統(tǒng)和大多數(shù)編程語(yǔ)言都直接支持Unicode。
現(xiàn)在,捋一捋ASCII編碼和Unicode編碼的區(qū)別:ASCII編碼是1個(gè)字節(jié),而Unicode編碼通常是2個(gè)字節(jié)。
字母A用ASCII編碼是十進(jìn)制的65,二進(jìn)制的01000001;
字符’0’用ASCII編碼是十進(jìn)制的48,二進(jìn)制的00110000,注意字符’0’和整數(shù)0是不同的;
漢字中已經(jīng)超出了ASCII編碼的范圍,用Unicode編碼是十進(jìn)制的20013,二進(jìn)制的01001110 00101101。
可以猜測(cè),如果把ASCII編碼的A用Unicode編碼,只需要在前面補(bǔ)0就可以,因此,A的Unicode編碼是00000000 01000001。
新的問(wèn)題又出現(xiàn)了:如果統(tǒng)一成Unicode編碼,亂碼問(wèn)題從此消失了。但是,如果你寫(xiě)的文本基本上全部是英文的話(huà),用Unicode編碼比ASCII編碼需要多一倍的存儲(chǔ)空間,在存儲(chǔ)和傳輸上就十分不劃算。
所以,本著節(jié)約的精神,又出現(xiàn)了把Unicode編碼轉(zhuǎn)化為“可變長(zhǎng)編碼”的UTF-8編碼。UTF-8編碼把一個(gè)Unicode字符根據(jù)不同的數(shù)字大小編碼成1-6個(gè)字節(jié),常用的英文字母被編碼成1個(gè)字節(jié),漢字通常是3個(gè)字節(jié),只有很生僻的字符才會(huì)被編碼成4-6個(gè)字節(jié)。如果你要傳輸?shù)奈谋景罅坑⑽淖址?#xff0c;用UTF-8編碼就能節(jié)省空間:
字符 ASCII Unicode UTF-8
A 01000001 00000000 01000001 01000001
中 x 01001110 00101101 11100100 10111000 10101101
UTF-8編碼有一個(gè)額外的好處,就是ASCII編碼實(shí)際上可以被看成是UTF-8編碼的一部分,所以,大量只支持ASCII編碼的歷史遺留軟件可以在UTF-8編碼下繼續(xù)工作。
總結(jié)
- 上一篇: 良性计算机病毒对计算有没有危害机系统,1
- 下一篇: 计算机组成SRAM,静态读写存储器(SR