引子
通過上一節(jié)講的二進制的知識,大家已經(jīng)知道計算機只認識二進制,生活中的數(shù)字要想讓計算機理解就必須轉(zhuǎn)換成二進制。十進制到二進制的轉(zhuǎn)換只能解決計算機理解數(shù)字的問題,那么文字要怎么讓計算機理解呢?
于是我們就選擇了一種曲線救國的方式,既然數(shù)字可以轉(zhuǎn)換成十進制,我們只要想辦法把文字轉(zhuǎn)換成數(shù)字劝术,這樣文字不就可以表示成二進制了么?
可是文字應(yīng)該怎么轉(zhuǎn)換成數(shù)字呢冒嫡?就是強制轉(zhuǎn)換啊瓣赂,簡單粗暴呀片拍。?我們自己強行約定了一個表煌集,把文字和數(shù)字對應(yīng)上,這張表就相當(dāng)于翻譯捌省,我們可以拿著一個數(shù)字來對比對應(yīng)表找到相應(yīng)的文字苫纤,反之亦然。
ASCII碼
這張表就是計算機顯示各種文字所禀、符號的基石呀
ASCII(American Standard Code for Information Interchange方面,美國信息交換標(biāo)準代碼)是基于拉丁字母的一套電腦編碼系統(tǒng),主要用于顯示現(xiàn)代英語和其他西歐語言色徘。它是現(xiàn)今最通用的單字節(jié)編碼系統(tǒng)恭金,并等同于國際標(biāo)準ISO/IEC 646。
由于計算機是美國人發(fā)明的褂策,因此横腿,最早只有127個字母被編碼到計算機里,也就是大小寫英文字母斤寂、數(shù)字和一些符號耿焊,這個編碼表被稱為ASCII編碼,比如大寫字母A的編碼是65遍搞,小寫字母z的編碼是122罗侯。后128個稱為擴展ASCII碼。
那現(xiàn)在我們就知道了上面的字母符號和數(shù)字對應(yīng)的表是早就存在的溪猿。那么根據(jù)現(xiàn)在有的一些十進制钩杰,我們就可以轉(zhuǎn)換成二進制的編碼串。
比如
一個空格對應(yīng)的數(shù)字是0? ? ? ? ? 翻譯成二進制就是0(注意字符'0'和整數(shù)0是不同的)
一個對勾√對應(yīng)的數(shù)字是251? ? ? 翻譯成二進制就是11111011
提問:假如我們要打印兩個空格一個對勾 寫作二進制就應(yīng)該是 0011111011诊县, 但是問題來了讲弄,我們怎么知道從哪兒到哪兒是一個字符呢?
論斷句的重要性與必要性:
上次在網(wǎng)上看到個新聞依痊,講是個小偷在上海被捕時高喊道:“我一定要當(dāng)上海賊王避除!”
正是由于這些字符串長的長,短的短胸嘁,寫在一起讓我們難以分清每一個字符的起止位置瓶摆,所以聰明的人類就想出了一個解決辦法,既然一共就這255個字符性宏,那最長的也不過是11111111八位赏壹,不如我們就把所有的二進制都轉(zhuǎn)換成8位的,不足的用0來替換衔沼。
這樣一來蝌借,剛剛的兩個空格一個對勾就寫作000000000000000011111011,讀取的時候只要每次讀8個字符就能知道每個字符的二進制值啦指蚁。
在這里菩佑,每一位0或者1所占的空間單位為bit(比特),這是計算機中最小的表示單位
每8個bit組成一個字節(jié)凝化,這是計算機中最小的存儲單位(畢竟你是沒有辦法存儲半個字符的)orz~
bit? ? ? ? ? 位稍坯,計算機中最小的表示單位
8bit = 1bytes 字節(jié),最小的存儲單位搓劫,1bytes縮寫為1B
1KB=1024B
1MB=1024KB
1GB=1024MB
1TB=1024GB
1PB=1024TB
1EB=1024PB
1ZB=1024EB
1YB=1024ZB
1BB=1024YB
GB2312 & GBK
英文問題是解決了瞧哟, 我們中文如何顯示呢? 美國佬設(shè)計ASSCII碼的時候應(yīng)該是沒考慮中國人有一天也能用上電腦枪向, 所以根本沒考慮中文的問題勤揩,上世界80年代,電腦進入中國秘蛔,把磚家們難倒了陨亡,媽的你個一ASSCII只能存256個字符,我常用漢字就幾千個深员,怎么玩负蠕??倦畅?勒緊褲腰帶還蘇聯(lián)貸款的時候我們都挺過來啦遮糖,這點小事難不到我們, 既然美帝的ASCII不支持中文叠赐,那我們自己搞張編碼表不就行了欲账, 于是我們設(shè)計出了GB2312編碼表,長成下面的樣子燎悍。一共存了6763個漢字敬惦。?
這個表格比較大,像上面的一塊塊的文字區(qū)域有72個谈山,這導(dǎo)致通過一個字節(jié)是沒辦法表示一個漢字的(因為一個字節(jié)最多允許256個字符變種俄删,你現(xiàn)在6千多個,只能2個字節(jié)啦奏路,2**16=65535個變種)畴椰。?
有了gb2312,我們就能愉快的寫中文啦鸽粉。?
但我們寫字竟然會出現(xiàn)中英混雜的情況斜脂,比如“我是小猿圈,我的英文名叫Apeland.”触机, 這種你怎么辦帚戳?這就要求你必須在gb2312里同時支持英文玷或,但是還不能是2個字節(jié)表示一個英文字母。人家ASCII用一個字符片任,你用2個偏友,那一個2mb大小的英文文檔只要一改編碼,就立刻變成4mb, 太坑爹对供,中國人你有錢也不能這么造呀位他。 所以中國磚家們又通過神奇手段兼容了ASSCII, 即遇到中文用2個字節(jié),遇到英文直接用ASCII的編碼产场。怎么做到的呢鹅髓??
如何區(qū)別連在一起的2個字節(jié)是代表2個英文字母,還是一個中文漢字呢京景? 中國人如此聰明窿冯,決定,如果2個字節(jié)連在一起醋粟,且每個字節(jié)的第1位(也就是相當(dāng)于128的那個2進制位)如果是1靡菇,就代表這是個中文,這個首位是128的字節(jié)被稱為高字節(jié)米愿。 也就是2個高字節(jié)連在一起厦凤,必然就是一個中文。?你怎么如此篤定育苟?因為0-127已經(jīng)表示了英文的絕大部分字符较鼓,128-255是ASCII的擴展表,表示的都是極特殊的字符违柏,一般沒什么用博烂。所以中國人就直接拿來用了。
自1980年發(fā)布gb2312之后漱竖,中文一直用著沒啥問題禽篱,隨著個人電腦進入千家萬戶,有人發(fā)現(xiàn)馍惹,自己的名字竟然打印不出來躺率,因為起的太生僻了。
于是1995年万矾, 磚家們又升級了gb2312, 加入更多字符悼吱,連什么藏語、維吾爾語良狈、日語后添、韓語、蒙古語什么的統(tǒng)統(tǒng)都包含進去了薪丁,國家統(tǒng)一亞洲的野心從這些基礎(chǔ)工作中就可見一斑哈遇西。 這個編碼叫GBK馅精,一直到現(xiàn)在,我們的windows電腦中文版本的編碼就是GBK.
編碼混戰(zhàn)時代
中國人在搞自己編碼的同時努溃,世界上其它非英語國家也得用電腦呀硫嘶,于是都搞出了自己的編碼,你可以想得到的是梧税,全世界有上百種語言,日本把日文編到Shift_JIS里称近,韓國把韓文編到Euc-kr里第队,
各國有各國的標(biāo)準,就會不可避免地出現(xiàn)沖突刨秆,結(jié)果就是凳谦,在多語言混合的文本中,顯示出來會有亂碼衡未。之前你從玩?zhèn)€日本游戲尸执,往自己電腦上一裝,就顯示亂碼了缓醋。?
這么亂極大了阻礙了不同國家的信息傳遞如失,于是聯(lián)合國出面,發(fā)誓要解決這個混亂局面送粱。?
因此褪贵,Unicode應(yīng)運而生。Unicode把所有語言都統(tǒng)一到一套編碼里抗俄,這樣就不會再有亂碼問題了脆丁。Unicode 2-4字節(jié) 已經(jīng)收錄136690個字符,并還在一直不斷擴張中...
Unicode標(biāo)準也在不斷發(fā)展动雹,但最常用的是用兩個字節(jié)表示一個字符(如果要用到非常偏僻的字符槽卫,就需要4個字節(jié))。現(xiàn)代操作系統(tǒng)和大多數(shù)編程語言都直接支持Unicode胰蝠。
Unicode有2個特點:
支持全球所有語言
可以跟各種語言的編碼自由轉(zhuǎn)換歼培,也就是說,即使你gbk編碼的文字 姊氓,想轉(zhuǎn)成unicode很容易丐怯。
為何unicode可以跟其它語言互相轉(zhuǎn)換呢? 因為有跟所有語言都有對應(yīng)關(guān)系哈翔横,這樣做的好處是可以讓那些已經(jīng)用gbk或其它編碼寫好的軟件容易的轉(zhuǎn)成unicode編碼 读跷,利于unicode的推廣。 下圖就是unicode跟中文編碼的對應(yīng)關(guān)系?
UTF-8?
新的問題又出現(xiàn)了:如果統(tǒng)一成Unicode編碼禾唁,亂碼問題從此消失了效览。但是无切,如果你寫的文本基本上全部是英文的話,用Unicode編碼比ASCII編碼需要多一倍的存儲空間丐枉,由于計算機的內(nèi)存比較大哆键,并且字符串在內(nèi)容中表示時也不會特別大,所以內(nèi)容可以使用unicode來處理瘦锹,但是存儲和網(wǎng)絡(luò)傳輸時一般數(shù)據(jù)都會非常多籍嘹,那么增加1倍將是無法容忍的!M湓骸辱士!
為了解決存儲和網(wǎng)絡(luò)傳輸?shù)膯栴},出現(xiàn)了Unicode Transformation Format听绳,學(xué)術(shù)名UTF颂碘,即:對unicode字符進行轉(zhuǎn)換,以便于在存儲和網(wǎng)絡(luò)傳輸時可以節(jié)省空間!
UTF-8: 使用1椅挣、2头岔、3、4個字節(jié)表示所有字符鼠证;優(yōu)先使用1個字符峡竣、無法滿足則使增加一個字節(jié),最多4個字節(jié)名惩。英文占1個字節(jié)澎胡、歐洲語系占2個、東亞占3個娩鹉,其它及特殊字符占4個
UTF-16: 使用2攻谁、4個字節(jié)表示所有字符;優(yōu)先使用2個字節(jié)弯予,否則使用4個字節(jié)表示戚宦。
UTF-32: 使用4個字節(jié)表示所有字符;
總結(jié):UTF 是為unicode編碼 設(shè)計 的一種 在存儲 和傳輸時節(jié)省空間的編碼方案锈嫩。
如果你要傳輸?shù)奈谋景罅坑⑽淖址苈ィ?b>UTF-8編碼就能節(jié)省空間:
字符ASCIIUnicodeUTF-8
A0100000100000000 0100000101000001
中x01001110 0010110111100100 10111000 10101101
從上面的表格還可以發(fā)現(xiàn),UTF-8編碼有一個額外的好處呼寸,就是ASCII編碼實際上可以被看成是UTF-8編碼的一部分艳汽,所以,大量只支持ASCII編碼的歷史遺留軟件可以在UTF-8編碼下繼續(xù)工作对雪。
搞清楚了ASCII河狐、Unicode和UTF-8的關(guān)系,我們就可以總結(jié)一下現(xiàn)在計算機系統(tǒng)通用的字符編碼工作方式:
在計算機內(nèi)存中,統(tǒng)一使用Unicode編碼馋艺,當(dāng)需要保存到硬盤或者需要傳輸?shù)臅r候栅干,就轉(zhuǎn)換為UTF-8編碼。
用記事本編輯的時候捐祠,從文件讀取的UTF-8字符被轉(zhuǎn)換為Unicode字符到內(nèi)存里碱鳞,編輯完成后,保存的時候再把Unicode轉(zhuǎn)換為UTF-8保存到文件踱蛀。
常用編碼介紹一覽表
編碼制定時間作用所占字節(jié)數(shù)
ASCII1967年表示英語及西歐語言8bit/1bytes
GB23121980年國家簡體中文字符集窿给,兼容ASCII2bytes
Unicode1991年國際標(biāo)準組織統(tǒng)一標(biāo)準字符集2bytes
GBK1995年GB2312的擴展字符集,支持繁體字星岗,兼容GB23122bytes
UTF-81992年不定長編碼1-3bytes
Py2 Vs Py3編碼
python生下來的時候 還沒有unicode&utf-8, 所以龜叔選用的默認編碼只能是ASCII, 一真到py2.7填大,用的還是ASCII, 導(dǎo)致Py默認只支持英文,想支持其它語言俏橘,必須單獨配置。?
Alexs-MacBook-Pro:day2 alex$morepy2編碼_ascii.py print("小猿圈")Alexs-MacBook-Pro:day2 alex$ python2.7 py2編碼_ascii.py? File"py2編碼_ascii.py", line 2SyntaxError: Non-ASCII character'\xe5'infilepy2編碼_ascii.py on line 2, but no encoding declared;see http://python.org/dev/peps/pep-0263/fordetails
直接寫中文執(zhí)行會報錯的圈浇。?
需在文件開頭聲明文件的編碼才能寫中文
# -*- encoding:utf-8 -*-print("小猿圈")
再執(zhí)行就不會有錯了寥掐。?
不過注意如果你的電腦 是windows系統(tǒng) , 你的系統(tǒng)默認編碼是GBK ,你聲明的時候要聲明成GBK, 不能是utf-8, 否則依然是亂碼磷蜀,因為gbk自然不認識utf-8.?
在Py2里編碼問題非常頭疼召耘,若不是徹底理解編碼之間的各種關(guān)系,會經(jīng)常容易出現(xiàn)亂碼而不知所措褐隆。
到了Py3推出后,終于把默認編碼改成了unicode, 同時文件存儲編碼變成了utf-8污它,意味著,不用任何聲明庶弃,你就可以寫各種語言文字在你的Python程序里衫贬。 從此,程序們手牽手過上了快樂的生活歇攻。?