字符編碼,在編程中,是一個讓學習者比較鬱悶的東西,好比一個str,若是都是英文,好說多了。但偏偏不是如此,中文是咱們不得不用的。因此,哪怕是初學者,都要了解並可以解決字符編碼問題。python
>>> name = '老齊' >>> name '\xe8\x80\x81\xe9\xbd\x90'
在你的編程中,你遇到過上面的情形嗎?認識最下面一行打印出來的東西嗎?看人家英文,就好多了git
>>> name = "qiwsir" >>> name 'qiwsir'
難道這是中文的錯嗎?看來投胎真的是一個技術活。是的,投胎是技術活,但上面的問題不是中文的錯。程序員
什麼是編碼?這是一個比較玄乎的問題。也很差下一個普通定義。我看到有的教材中有定義,不敢說他的定義不對,至少能夠說不容易理解。github
古代打仗,擊鼓進攻、鳴金收兵,這就是編碼。吧要傳達給士兵的命令對應爲必定的其它形式,好比命令「進攻」,通過如此的信息傳遞:面試
以上過程比較簡單。其實,真實的編碼和解碼過程,要複雜了。不過,原理都差很少的。編程
舉一個彷佛遙遠,其實不久前人們都在使用的東西作例子:電報segmentfault
電報是通訊業務的一種,在19世紀初發明,是最先使用電進行通訊的方法。電報大爲加快了消息的流通,是工業社會的其中一項重要發明。早期的電報只能在陸地上通信,後來使用了海底電纜,開展了越洋服務。到了20世紀初,開始使用無線電撥發電報,電報業務基本上已能抵達地球上大部份地區。電報主要是用做傳遞文字訊息,使用電報技術用做傳送圖片稱爲傳真。網絡
中國首條出現電報線路是1871年,由英國、俄國及丹麥敷設,從香港經上海至日本長崎的海底電纜。因爲清政府的反對,電纜被禁止在上海登錄。後來丹麥公司不理清政府的禁令,將線路引至上海公共租界,並在6月3日起開始收發電報。至於首條自主敷設的線路,是由福建巡撫丁日昌在臺灣所建,1877年10月完工,鏈接臺南及高雄。1879年,北洋大臣李鴻章在天津、大沽及北塘之間架設電報線路,用做軍事通信。1880年,李鴻章奏準開辦電報總局,由盛宣懷任總辦。並在1881年12月開通天津至上海的電報服務。李鴻章説:「五年來,我國創設沿江沿海各省電線,總計一萬多裏,國家所費無多,鉅款來自民間。當時正值法人挑釁,將帥報告軍情,朝廷傳達指示,均相機而動,無絲毫阻礙。中國自古用兵,從未如此神速。出使大臣往來問答,朝發夕至,相隔萬里好似同居庭院。舉設電報一舉三得,既防止外敵侵略,又增強國防,亦有利於商務。」天津官電局於庚子遭亂全毀。1887年,臺灣巡撫劉銘傳敷設了福州至臺灣的海底電纜,是中國首條海底電纜。1884年,北京電報開始建設,採用"安設雙線,由通州展至京城,以一端引入署中,專遞官信,以一端擇地安置用便商民",同年8月5日,電報線路開始建設,全部電線杆一概漆成紅色。8月22日,位於北京崇文門外大街西的喜鵲衚衕的外城商用電報局開業。同年8月30日,位於崇文門內泡子和以西的呂公堂開局,專門收發官方電報。函數
爲了傳達漢字,電報部門準備由4位數字或3位羅馬字構成的代碼,即中文電碼,採用發送前將漢字改寫成電碼發出,收電報後再將電碼改寫成漢字的方法。學習
列位看官注意了,這裏出現了電報中用的「中文電碼」,這就是一種編碼,將漢字對應成阿拉伯數字,從而可以用電報發送漢字。
1873年,法國駐華人員威基傑參照《康熙字典》的部首排列方法,挑選了經常使用漢字6800多個,編成了第一部漢字電碼本《電報新書》。
電報中的編碼被稱爲摩爾斯電碼,英文是Morse Code
摩爾斯電碼(英語:Morse Code)是一種時通時斷的信號代碼,經過不一樣的排列順序來表達不一樣的英文字母、數字和標點符號。是由美國人薩繆爾·摩爾斯在1836年發明。
摩爾斯電碼是一種早期的數字化通訊形式,可是它不一樣於現代只使用0和1兩種狀態的二進制代碼,它的代碼包括五種:點(.)、劃(-)、每一個字符間短的停頓(在點和劃之間的停頓)、每一個詞之間中等的停頓、以及句子之間長的停頓
看來電報員是一個技術活,不一樣長短的停頓都表明了不一樣意思。哦,對了,有一個老片子《永不消逝的電波》,看完以後保證你才知道,裏面根本就沒有講電報是怎麼編碼的。
摩爾斯電碼在海事通信中被做爲國際標準一直使用到1999年。1997年,當法國海軍中止使用摩爾斯電碼時,發送的最後一條消息是:「全部人注意,這是咱們在永遠沉寂以前最後的一聲吶喊!」
我瞪着眼看了老長時間,這兩行不是同樣的嗎?
無論這個了,總之,這就是編碼。
先抄一段維基百科對字符編碼的解釋:
字符編碼(英語:Character encoding)、字集碼是把字符集中的字符編碼爲指定集合中某一對象(例如:比特模式、天然數串行、8位組或者電脈衝),以便文本在計算機中存儲和經過通訊網絡的傳遞。常見的例子包括將拉丁字母表編碼成摩斯電碼和ASCII。其中,ASCII將字母、數字和其它符號編號,並用7比特的二進制來表示這個整數。一般會額外使用一個擴充的比特,以便於以1個字節的方式存儲。
在計算機技術發展的早期,如ASCII(1963年)和EBCDIC(1964年)這樣的字符集逐漸成爲標準。但這些字符集的侷限很快就變得明顯,因而人們開發了許多方法來擴展它們。對於支持包括東亞CJK字符家族在內的寫做系統的要求能支持更大量的字符,而且須要一種系統而不是臨時的方法實現這些字符的編碼。
在這個世界上,有好多不一樣的字符編碼。可是,它們不是本身隨便搞搞的。而是要有必定的基礎,每每是以名叫ASCII的編碼爲基礎,這裏邊也應該包括北朝鮮吧(不知道他們用什麼字符編碼,瞎想的,別當真,不表明本教材立場,只表明瞎想)。
ASCII(pronunciation: 英語發音:/ˈæski/ ASS-kee1,American Standard Code for Information Interchange,美國信息交換標準代碼)是基於拉丁字母的一套電腦編碼系統。它主要用於顯示現代英語,而其擴展版本EASCII則能夠部分支持其餘西歐語言,並等同於國際標準ISO/IEC 646。因爲萬維網使得ASCII廣爲通用,直到2007年12月,逐漸被Unicode取代。
上面的引文中已經說了,如今咱們用的編碼標準,已經不是ASCII了,我上大學那時候老師講的仍是ASCII呢(最坑爹的是貴國的大學教育,前幾天面試一個大學畢業生,計算機專業的,他告訴我他的老師給他們講的就是ASCII爲編碼標準呢,我說你別埋汰老師了,你去看看教材,今天這哥們真給我發短信了,告訴我教材上就是這麼說的。),時代變遷,如今已經變成了Unicode了,那麼什麼是Unicode編碼呢?仍是抄一段來自維基百科的說明(須要說明一下,本講不是我qiwsir在講,是維基百科在講,我只是一個配角,哈哈)
Unicode(中文:萬國碼、國際碼、統一碼、單一碼)是計算機科學領域裏的一項業界標準。它對世界上大部分的文字系統進行了整理、編碼,使得電腦能夠用更爲簡單的方式來呈現和處理文字。
Unicode伴隨着通用字符集的標準而發展,同時也以書本的形式對外發表。Unicode至今仍在不斷增修,每一個新版本都加入更多新的字符。目前最新的版本爲7.0.0,已收入超過十萬個字符(第十萬個字符在2005年獲採納)。Unicode涵蓋的數據除了視覺上的字形、編碼方法、標準的字符編碼外,還包含了字符特性,如大小寫字母。
聽這名字:萬國碼,那就必定包含了中文嘍。的確是。可是,光有一個Unicode還不行,由於....(此處省略若干字,看官能夠到上面給出的維基百科鏈接中看),還要有其它的一些編碼實現方式,Unicode的實現方式稱爲Unicode轉換格式(Unicode Transformation Format,簡稱爲UTF),因而乎有了一個咱們在不少時候都會看到的utf-8。
什麼是utf-8,仍是看維基百科上怎麼說的吧
UTF-8(8-bit Unicode Transformation Format)是一種針對Unicode的可變長度字符編碼,也是一種前綴碼。它能夠用來表示Unicode標準中的任何字符,且其編碼中的第一個字節仍與ASCII兼容,這使得原來處理ASCII字符的軟件無須或只須作少部份修改,便可繼續使用。所以,它逐漸成爲電子郵件、網頁及其餘存儲或發送文字的應用中,優先採用的編碼。
再也不多引用了,若是要看更多,請到原文。
看官如今是否是就理解了,前面寫程序的時候,曾經出現過:coding:utf-8的字樣。就是在告訴python咱們要用什麼字符編碼呢。
歷史部分說完了,接下怎麼講?比較麻煩了。由於無論怎麼講,都不是三言兩語說清楚的。姑且從encode()和decode()兩個內置函數起吧。
codecs.encode(obj[, encoding[, errors]]):Encodes obj using the codec registered for encoding.
codecs.decode(obj[, encoding[, errors]]):Decodes obj using the codec registered for encoding.
python2默認的編碼是ascii,經過encode能夠將對象的編碼轉換爲指定編碼格式,而decode是這個過程的逆過程。
作一個實驗,才能理解:
>>> a = "中" >>> type(a) <type 'str'> >>> a '\xe4\xb8\xad' >>> len(a) 3 >>> b = a.decode() >>> b u'\u4e2d' >>> type(b) <type 'unicode'> >>> len(b) 1
這個實驗不作以前,或許看官還不是很迷茫(由於不知道,知道的越多越迷茫),實驗作完了,本身也迷茫了。別急躁,對編碼問題的理解,要慢慢來,若是一時理解不了,也確定理解不了,就先注意按照要求作,作着作着就豁然開朗了。
上面試驗中,變量a引用了一個字符串,所謂字符串(str),嚴格地將是字節串,它是通過編碼後的字節組成的序列。也就是你在上面的實驗中,看到的是「中」這個字在計算機中編碼以後的字節表示。(關於字節,看官能夠google一下)。用len(a)來度量它的長度,它是由三個字節組成的。
而後經過decode函數,將字節串轉變爲字符串,而且這個字符串是按照unicode編碼的。在unicode編碼中,一個漢字對應一個字符,這時候度量它的長度就是1.
反過來,一個unicode編碼的字符串,也能夠轉換爲字節串。
>>> c = b.encode('utf-8') >>> c '\xe4\xb8\xad' >>> type(c) <type 'str'> >>> c == a True
關於編碼問題,先到這裏,點到爲止吧。由於再扯,還會扯出問題來。看官確定感到不滿意,由於尚未知其因此然。不要緊,請盡情google,便可解決。
這個問題是一個具備很強操做性的問題。我這裏有一個經驗總結,分享一下,供參考:
首先,提倡使用utf-8編碼方案,由於它跨平臺不錯。
經驗一:在開頭聲明:
# -*- coding: utf-8 -*-
有朋友問我-*-有什麼做用,那個就是爲了好看,愛漂亮之心人皆有,更況且程序員?固然,也能夠寫成:
# coding:utf-8
經驗二:遇到字符(節)串,馬上轉化爲unicode,不要用str(),直接使用unicode()
unicode_str = unicode('中文', encoding='utf-8') print unicode_str.encode('utf-8')
經驗三:若是對文件操做,打開文件的時候,最好用codecs.open,替代open(這個後面會講到,先放在這裏)
import codecs codecs.open('filename', encoding='utf8')
我還收集了網上的一片文章,也挺好的,推薦給看官:Python2.x的中文顯示方法
最後告訴給我,若是用python3,坑爹的編碼問題就不煩惱了。