Python字元編碼理解

2021-07-03 08:56:18 字數 3551 閱讀 8220

長久以來,一直對編碼有所不理解,現在梳理一下。

首先要明白幾個概念:字元,字符集,字元編碼

什麼是字元呢? 很簡單,比如乙個漢字就是乙個字元,乙個「你」就是乙個字元;而同樣的,對於英語來說,「a」是乙個字元;「3」也是乙個字元。不同的語言,不同的表示方式,都是乙個字元。

那麼是什麼是字符集呢? 字符集就是,很多個字元的集合。那麼不同的字符集,就代表著不同的字元的集合。比如說,:ascii字符集、iso 8859字符集、gb2312字符集、big5字符集、gb18030字符集、unicode字符集等。對於這些字符集來說,每個都有自己所涵蓋的字元。比如ascii編碼涵蓋的就只有128個字元;而unicode幾乎可以包含所有的字元。所以對於某個字元來說,可能是這個字符集中的,也可能是另外的字符集中的。

字元編碼呢,就是對字元進行某種編碼。實際上,我們在劃分字符集的時候,就相應的劃分了對應的編碼方式(否則的話,乙個字元,對應到兩個不同的字符集有什麼意義呢?就是因為他們有不同的編碼方法啊)。字符集中的字元(可以是英語,漢語,標點等等,是這個字元最原始的樣子,比如漢字的「漢」,就是這個字元本身,而不是其他的樣子)按照字符集中規定的編碼方式,將這個字元進行相應的編碼。至於如何編碼呢,下面我們繼續說。

1、ascii 編碼

一開始的時候,計算機世界只有英文。而ascii(american standard code for information interchange),是一種單位元組的編碼。而單位元組可以表示256個不同的字元,可以表示所有的英文本元和許多的控制符號。不過ascii只用到了其中的一半(\x80以下)

2、ansi編碼

很明顯,ascii編碼是不夠的,因為他只能為美帝所用。所以各個國家都針對自己的情況,對於編碼方式進行了擴充套件。每個語言就制定了一套自己的編碼,由於單位元組能表示的字元太少,而且同時也需要與ascii編碼保持相容,所以這些編碼紛紛使用了多位元組來表示字元,如gb***、big***等等,他們的規則是,如果第乙個位元組是\x80以下,則仍然表示ascii字元;而如果是\x80以上,則跟下乙個位元組一起(共兩個位元組)表示乙個字元,然後跳過下乙個位元組,繼續往下判斷。

不同的國家和地區制定了不同的標準,由此產生了gb2312,big5,jis等各自的編碼標準。這些使用2個位元組來代表乙個字元的各種漢字延伸編碼方式,稱為 ansi 編碼。在簡體中文系統下,ansi 編碼代表 gb2312 編碼,在日文作業系統下,ansi 編碼代表 jis 編碼。

不同 ansi 編碼之間互不相容,當資訊在國際間交流時,無法將屬於兩種語言的文字,儲存在同一段 ansi 編碼的文字中。

中文dos、中文/日文windows 95/98時代系統內碼使用的是ansi編碼(本地化)

在使用ansi編碼支援多語言階段,每個字元使用乙個位元組或多個位元組來表示(mbcs,multi-byte character system),因此,這種方式存放的字元也被稱作多位元組字元。比如,」中文123」 在中文 windows 95 記憶體中為7個位元組,每個漢字佔2個位元組,每個英文和數字字元佔1個位元組。

ansi可以了,但是不足夠好:因為他對於交流不利。於是出現了unicode。

3、unicode

為了使國際間資訊交流更加方便,國際組織制定了 unicode 字符集,為各種語言中的每乙個字元設定了統一並且唯一的數字編號,以滿足跨語言、跨平台進行文字轉換、處理的要求。

unicode字符集可以簡寫為ucs(unicode character set)。早期的unicodeunicode標準有ucs-2、ucs-4的說法。ucs-2用兩個位元組編碼,ucs-4用4個位元組編碼。

在 unicode 被採用之後,計算機存放字串時,改為存放每個字元在 unicode 字符集中的序號。目前計算機一般使用 2 個位元組(16 位)來存放乙個序號(dbcs,double byte character system),因此,這種方式存放的字元也被稱作寬位元組字元。比如,字串 「中文123」 在 windows 2000 下,記憶體中實際存放的是 5 個序號,一共10個位元組。

unicode字符集包含了各種語言中使用到的所有「字元」。用來給 unicode 字符集編碼的標準有很多種,比如:utf-8, utf-7, utf-16, unicodelittle, unicodebig 等。

後來,有人開始覺得太多編碼導致世界變得過於複雜了,讓人腦袋疼,於是大家坐在一起拍腦袋想出來乙個方法:所有語言的字元都用同一種字符集來表示,這就是unicode。

最初的unicode標準ucs-2使用兩個位元組表示乙個字元,所以你常常可以聽到unicode使用兩個位元組表示乙個字元的說法。但過了不久有人覺得256*256太少了,還是不夠用,於是出現了ucs-4標準,它使用4個位元組表示乙個字元,不過我們用的最多的仍然是ucs-2。

ucs(unicode character set)還僅僅是字元對應碼位的一張表而已,比如」漢」這個字的碼位是6c49。字元具體如何傳輸和儲存則是由utf(ucs transformation format)來負責。

一開始這事很簡單,直接使用ucs的碼位來儲存,這就是utf-16,比如,」漢」直接使用\x6c\x49儲存(utf-16-be),或是倒過來使用\x49\x6c儲存(utf-16-le)。但用著用著美國人覺得自己吃了大虧,以前英文本母只需要乙個位元組就能儲存了,現在大鍋飯一吃變成了兩個位元組,空間消耗大了一倍……於是utf-8橫空出世。

utf-8是一種很彆扭的編碼,具體表現在他是變長的,並且相容ascii,ascii字元使用1位元組表示。然而這裡省了的必定是從別的地方摳出來的,你肯定也聽說過utf-8裡中文字元使用3個位元組來儲存吧?4個位元組儲存的字元更是在淚奔……(具體ucs-2是怎麼變成utf-8的請自行搜尋)

在 unicode 被採用之後,計算機存放字串時,改為存放每個字元在 unicode 字符集中的序號。目前計算機一般使用 2 個位元組(16 位)來存放乙個序號(dbcs,double byte character system),因此,這種方式存放的字元也被稱作寬位元組字元。這就當然,這就意味著,所有的符號,都要用兩個位元組來表示。但是,但用著用著美國人覺得自己吃了大虧,以前英文本母只需要乙個位元組就能儲存了,現在大鍋飯一吃變成了兩個位元組,空間消耗大了一倍……於是utf-8橫空出世。

5.2.1 utf-8

ucs-2編碼(16進製制) utf-8 位元組流(二進位制)

0000 - 007f 0******x

0080 - 07ff 110***xx 10******

0800 - ffff 1110***x 10****** 10******

例如「漢」字的unicode編碼是6c49。6c49在0800-ffff之間,所以肯定要用3位元組模板了:1110***x 10****** 10******。將6c49寫成二進位制是:0110 110001 001001,用這個位元流依次代替模板中的x,得到:11100110 10110001 10001001,即e6 b1 89。

可見utf-8是變長的,將unicode編碼為00000000-0000007f的字元,用單個位元組來表示; 00000080-000007ff的字元用兩個位元組表示;00000800-0000ffff的字元用3位元組表示。因為目前為止unicode-16規範沒有指定ffff以上的字元,所以utf-8最多是使用3個位元組來表示乙個字元。但理論上來說,utf-8最多需要用6位元組表示乙個字元。

utf-8相容ascii。

可見對於utf-8來說,他是變長的。

深入理解python字元編碼

整理python在檔案讀取時報錯和cpu執行時字串報錯unicodeencodeerror unicodedecodeerror 解釋py2和py3字串資料型別,和bytes和unicode在py2和py3中的不同表現形式。1.編碼和解碼 2.python 2中的字元編碼 3.python 3中的字...

字元編碼問題理解

2015年8月5日 09 52 31 字元編碼問題理解 1.檔案儲存有編碼格式,檔案中的字元以這種格式儲存在其中 2.程式預設接收那種編碼格式的字元是別外一回事,與檔案格式無關,如普通的中文版本windwos系統的控制台與普通程式中,預設的窄字元的編碼格式是gbk的 而linux的控制台與http請...

python字符集編碼深入理解

在python中和字串相關的型別,分別是str,unicode兩種不同的型別 basestring str unicode指令碼字元編碼 指指令碼檔案本身是用何種字元編碼的,預設情況python直譯器 直譯器就是執行python 程式的程式 認為指令碼是ascii碼 test.py print 你好...