python的 隨手記----字元編碼與轉碼,python隨手記
一.前提
那麼到底什麼是編碼呢? //ASCII 記住一句話:電腦中的所有資料,不論是文字、圖片、視頻、還是音頻檔案,本質上最終都是按照類似 01010101 的二進位儲存的。 再說簡單點,電腦只懂位元字! 所以,目的明確了:如何將我們能識別的符號唯一的與一組位元字對應上?於是美利堅的同志想到通過一個電平的高低狀態來代指0或1, 八個電平做為一組就可以表示出 256種不同狀態,每種狀態就唯一對應一個字元,比如A--->00010001,而英文只有26個字元,算上一些特殊字元和數字,128個狀態也夠 用了;每個電平稱為一個位元為,約定8個位元位構成一個位元組,這樣電腦就可以用127個不同位元組來儲存英語的文字了。這就是ASCII編碼。 擴充ANSI編碼 剛才說了,最開始,一個位元組有八位,但是最高位沒用上,預設為0;後來為了電腦也可以表示拉丁文,就將最後一位也用上了, 從128到255的字元集對應拉丁文啦。至此,一個位元組就用滿了! //GB2312 電腦漂洋過海來到中國後,問題來了,電腦不認識中文,當然也沒法顯示中文;而且一個位元組所有狀態都被佔滿了,萬惡的帝國主義亡 我之心不死啊!我黨也是棒,自力更生,自己重寫一張表,直接生猛地將擴充的第八位對應拉丁文全部刪掉,規定一個小於127的字元的意 義與原來相同,但兩個大於127的字元連在一起時,就表示一個漢字,前面的一個位元組(他稱之為高位元組)從0xA1用到0xF7,後面一個位元組 (低位元組)從0xA1到0xFE,這樣我們就可以組合出大約7000多個簡體漢字了;這種漢字方案叫做 “GB2312”。GB2312 是對 ASCII 的中文擴充。 //GBK 和 GB18030編碼 但是漢字太多了,GB2312也不夠用,於是規定:只要第一個位元組是大於127就固定表示這是一個漢字的開始,不管後面跟的是不是擴充字元集裡的 內容。結果擴充之後的編碼方案被稱為 GBK 標準,GBK 包括了 GB2312 的所有內容,同時又增加了近20000個新的漢字(包括繁體字)和符號。 //UNICODE編碼: 很多其它國家都搞出自己的編碼通訊協定,彼此間卻相互不支援。這就帶來了很多問題。於是,國際標誰化組織為了統一編碼:提出了標準編碼准 則:UNICODE 。 UNICODE是用兩個位元組來表示為一個字元,它總共可以組合出65535不同的字元,這足以覆蓋世界上所有符號(包括甲骨文) //utf8: unicode都一統天下了,為什麼還要有一個utf8的編碼呢? 大家想,對於英文世界的人們來講,一個位元組完全夠了,比如要儲存A,本來00010001就可以了,現在吃上了unicode的大鍋飯, 得用兩個位元組:00000000 00010001才行,浪費太嚴重! 基於此,美利堅的科學家們提出了天才的想法:utf8. UTF-8(8-bit Unicode Transformation Format)是一種針對Unicode的可變長度字元編碼,它可以使用1~4個位元組表示一個符號,根據 不同的符號而變化位元組長度,當字元在ASCII碼的範圍時,就用一個位元組表示,所以是相容ASCII編碼的。 這樣顯著的好處是,雖然在我們記憶體中的資料都是unicode,但當資料要儲存到磁碟或者用於網路傳輸時,直接使用unicode就遠不如utf8省空間啦! 這也是為什麼utf8是我們的推薦編碼方式。 Unicode與utf8的關係: 一言以蔽之:Unicode是記憶體編碼錶示方案(是規範),而UTF是如何儲存和傳輸Unicode的方案(是實現)這也是UTF與Unicode的區別。
我們只需要知道unicode是萬國碼,而utf-8還有gbk都是由unicode中拓展出來的,於是我們utf-8轉為gbk是形式是:先轉成unicode再轉成gbk;同理其他編碼轉化成utf-8,也先向unicode轉化,再轉成utf-8
python3字串是以Unicode編碼的,文本總是Unicode,由str類型表示,位元據則由bytes類型表示
其中的容易誤解的地方:
(1)py3裡預設檔案編碼就是utf-8,所以可以直接寫中文,也不需要檔案頭聲明編碼了
(2)你聲明的變數預設是unicode編碼,即使你檔案頭聲明編碼是utf-8,也不是utf-8, 因為預設即是unicode了
import sys
print(sys.getdefaultencoding())#列印系統的預設編碼
#s=u"你好"#加一個u表示這個你好是upython預設是unicodenicode的編碼格式,輸出結果發現和不加u是一樣的,表示python預設是unicode
s="你好"#,即這個s是unicode的編碼格式
print(s.encode("utf-8"))#encode解碼,即告訴系統s向utf-8轉換,輸出一個byte類型的對象
print(s.encode("utf-8").decode("gbk"))#表示再向gbk格式轉碼
print(s.encode("gbk"))
print(s.encode("utf-8").decode("utf-8").encode("gbk"))
print(s.encode())#預設不寫表示utf-8
print(s.encode("utf-8").decode())
輸出結果:
>>>utf-8
>>>b'\xe4\xbd\xa0\xe5\xa5\xbd'#b'表示byte類型
>>>浣犲ソ >>>b'\xc4\xe3\xba\xc3'
>>>b'\xc4\xe3\xba\xc3'
>>>b'\xe4\xbd\xa0\xe5\xa5\xbd'
>>>你好