在閱讀本文之前,相信你一定會有以下的疑問苞七。
A.2進制藐守、4進制、8進制蹂风、10進制卢厂、16進制,計算機到底是用哪種進制惠啄?
B.1kb 是1000字節(jié)慎恒?1000比特?還是1024撵渡?
C.計算機表示的數(shù)融柬,什么時候是2進制表示?什么時候是其他進制表示的趋距?
D.為什么有各種各樣的編碼粒氧?相互之間有何區(qū)別?
E.網(wǎng)頁上的數(shù)據(jù)為utf-8編碼节腐。獲取其數(shù)據(jù)后外盯,直接寫入到txt中,寫入的是bit流翼雀?
F.這種bit流是什么方式表示的饱苟?16進制?8進制狼渊?
G.如果遇到兩種編碼的文件箱熬,其數(shù)據(jù)放到一起之后,難道應(yīng)該分別進行編碼解碼?
--------------------------------------------------------------------------------------------------
1.計算機底層使用哪種進制城须?
(1)計算機內(nèi)部是由集成電路這種電子部件構(gòu)成的护锤,電路只可以表示兩種狀態(tài):電壓高低、電流有無酿傍、電路通電斷電。
(2)兩種狀態(tài)更穩(wěn)定驱入,也更容易區(qū)分赤炒。
(3)容易實現(xiàn)邏輯運算。
綜合以上特性亏较,計算機內(nèi)部只能處理二進制莺褒。因此,無論最后以何種方式表示這個二進制代表的數(shù)雪情,底層的計數(shù)方式為二進制遵岩!
2.字節(jié)與比特?
進制是按照進位方式計數(shù)的數(shù)制系統(tǒng)巡通,進位方式計數(shù)含有基數(shù)和位權(quán)這兩個參數(shù)尘执。
二進制數(shù) 110 表示 1*2^2 + 1*2^1 + 0*2^0 = 6? ?1、1宴凉、0為基數(shù) 位權(quán)為2^2誊锭、2^1、2^0
底層?11111111 —— 可以使用 255(十進制)表示弥锄、 也可以使用 FF(16進制)丧靡、甚至是四進制3333
由此可以衍生出各個進制對數(shù)的表示。但考慮到計算機內(nèi)部處理的其實是二進制籽暇,因此温治,我們以此為入口進行分析。
1位的二進制數(shù)范圍在0-1(0-1)
2位的二進制數(shù)范圍在0-3(00-11)
3位的二進制數(shù)范圍在0-7(000-111)
4位的二進制數(shù)范圍在0-15(0000-1111)
8位的二進制數(shù)范圍在0-255(00000000-11111111)
當(dāng)要表示的數(shù)逐漸變大的時候戒悠,以二進制方式計數(shù)的話熬荆,位數(shù)將會逐漸增多。內(nèi)部計算機中占用的“格子”也會增加救崔。計算機中惶看,每1位二進制數(shù)所占的“格子”叫做bit(比特),八個bite構(gòu)成一個Byte(字節(jié))六孵。
3.計算機中數(shù)據(jù)的表示纬黎?
計算機存儲信息的基本單位是“字節(jié)”即Byte。一個Byte=8bit
即一個字節(jié)等于八個二進制位劫窒。表示數(shù)的范圍為0-255
字節(jié)這個單位在實際使用中實在是太小的本今。常用的比字節(jié)大的單位還有:
1KB(千字節(jié))=1024Byte?
1MB(兆字節(jié))=1024KB
1GB(吉字節(jié))=1024MB
1TB(太字節(jié))=1024GB
之所以之間倍數(shù)為1024,讓我們來設(shè)想一下某人讓?1?KB?=?1000?Byte。
然后計算機會說:“有個問題想不通冠息?1?KB?為什么要等于?1111101000?Byte挪凑??逛艰?為什么不能等于?10000000000?Byte?磅锾肌?散怖?菇绵??” k是倍數(shù)的簡稱镇眷,也是考慮到2進制10000000000的1024咬最,所以不代表1000。
底層原理是以二進制來表示實際的數(shù)欠动,而二進制的位權(quán)是以8位bit的字節(jié)進行存儲永乌,因此在實際的數(shù)字上,要么是8位具伍、要么是16位翅雏、要么是32位,對應(yīng)的就是一個字節(jié)人芽、兩個字節(jié)枚荣、三個字節(jié)。
4.編碼問題詳解
UnicodeEncodeError: 'gbk' codec can't encode character '\u27a2' in position 119: illegal multibyte sequence
UnicodeEncodeError: 'gbk' codec can't encode character '\xf4' in position 264: illegal multibyte sequence
UnicodeEncodeError: 'gbk' codec can't encode character '\ufeff' in position 277: illegal multibyte sequence
UnicodeEncodeError: 'gbk' codec can't encode character '\u2122' in position 212: illegal multibyte sequence
相信使用python的各位大胸弟都會遇到類似的問題啼肩,尤其是在mac上碼好的代碼橄妆,放到windows下,突然出現(xiàn)以上的錯誤祈坠。心態(tài)絕對會爆炸害碾。
帶著這個問題,我們來研究一下編碼問題赦拘。
(1)編碼慌随、解碼
encode字面意思:編碼,編制成計算機語言躺同。
decode字面意思:解碼阁猜,分析及譯解電子信號,找出實際意思蹋艺。
第一部分我們已經(jīng)知道剃袍,一個字符計算機底層數(shù)據(jù)是以二進制的bit流表示的。一般而言捎谨,表示這個bit流采用16進制方式民效。如:
str ='辣條'
print(str.encode())
輸出結(jié)果為:b'\xe8\xbe\xa3\xe6\x9d\xa1'? 其中的“\x”?表示十六進制憔维。
那么當(dāng)出現(xiàn)b'\xe8\xbe\xa3\xe6\x9d\xa1'的時候,它代表的是什么畏邢?這時候就用到了編碼方式业扒。
當(dāng)遇到這樣一串bit流,就需要找出正確的密碼本舒萎,從密碼本中分析電子信號程储,找出真實意思。
(2)密碼本(各種編碼及之間的關(guān)系)
由于計算機是美國人發(fā)明的臂寝,因此虱肄,最早只有127個字符被編碼到計算機里,也就是大小寫英文字母交煞、數(shù)字和一些符號,這個編碼表被稱為ASCII編碼斟或,比如大寫字母A的編碼是65素征,小寫字母z的編碼是122。
但是要處理中文顯然一個字節(jié)是不夠的萝挤,至少需要兩個字節(jié)御毅,而且還不能和ASCII編碼沖突,所以怜珍,中國制定了GB2312編碼端蛆,用來把中文編進去。
你可以想得到的是酥泛,全世界有上百種語言今豆,日本把日文編到Shift_JIS里,韓國把韓文編到Euc-kr里柔袁,各國有各國的標(biāo)準(zhǔn)呆躲,就會不可避免地出現(xiàn)沖突,結(jié)果就是捶索,在多語言混合的文本中插掂,顯示出來會有亂碼。
因此腥例,Unicode應(yīng)運而生辅甥。Unicode把所有語言都統(tǒng)一到一套編碼里,這樣就不會再有亂碼問題了燎竖。
Unicode標(biāo)準(zhǔn)也在不斷發(fā)展璃弄,但最常用的是用兩個字節(jié)表示一個字符(如果要用到非常偏僻的字符,就需要4個字節(jié))」够兀現(xiàn)代操作系統(tǒng)和大多數(shù)編程語言都直接支持Unicode谢揪。
I? ? 0049
t? ? 0074
'? ? 0027
s? ?0073
? ? ?0020
知 77e5
乎 4e4e
日 65e5
報 62a5
以上就是“It's? 知乎日報” unicode字符集的編碼表蕉陋。統(tǒng)一成Unicode編碼后,當(dāng)出現(xiàn)編碼后的數(shù)據(jù)拨扶,我們也可以將其翻譯出它的實際意思凳鬓。當(dāng)然,在找出其真實的意思之前患民,還有一步缩举,那就是翻譯的規(guī)則是什么?
unicode是一個字符集匹颤,里面幾乎包含了目前世界上已知的所有字符仅孩,且該字符集將二進制代碼和字符形成一一映射,即一個字符對應(yīng)且只對應(yīng)一個二進制代碼印蓖,反過來辽慕,一個二進制代碼對應(yīng)且只對應(yīng)一個字符。如果我們有一個字符赦肃,那么通過Unicode字符集很容易找到該字符對應(yīng)的二進制碼溅蛉,但是,反過來他宛,可能會出現(xiàn)混亂船侧。
用通信理論的思路可以理解為:
unicode是信源編碼,對字符集數(shù)字化;
utf8是信道編碼厅各,為更好的存儲和傳輸镜撩。
新的問題又出現(xiàn)了:如果統(tǒng)一成Unicode編碼,亂碼問題從此消失了队塘。但是袁梗,如果你寫的文本基本上全部是英文的話,用Unicode編碼比ASCII編碼需要多一倍的存儲空間憔古,在存儲和傳輸上就十分不劃算围段。
所以,本著節(jié)約的精神投放,又出現(xiàn)了把Unicode編碼轉(zhuǎn)化為“可變長編碼”的UTF-8編碼奈泪。UTF-8編碼把一個Unicode字符根據(jù)不同的數(shù)字大小編碼成1-6個字節(jié),常用的英文字母被編碼成1個字節(jié)灸芳,漢字通常是3個字節(jié)涝桅,只有很生僻的字符才會被編碼成4-6個字節(jié)。如果你要傳輸?shù)奈谋景罅坑⑽淖址友肬TF-8編碼就能節(jié)省空間冯遂。
ASCII編碼 ——>(GB2312、Shift_JIS谒获、Euc-kr蛤肌。壁却。。各種沖突)——>unicode全世界語言整合到一起——>UTF-8/UTF-16
一句話裸准,utf8是對unicode字符集進行編碼的一種編碼方式展东。
(3)字符串
在python3.6中,字符串'辣條'字符編碼方式為unicode炒俱,unicode字符集的編碼方式為utf-8盐肃。所以python3.6中,字符串'辣條'的默認(rèn)編碼方式utf-8权悟。
可以理解utf是對unicode字符集的編碼方式砸王,就像 ascall碼,但是gb2312峦阁,gbk谦铃,iso-8859-1這些不但是字符集也是編碼方式。
str = '辣條'
print(str.encode('utf-8'))