基本概念
字符(Character)
在電腦和電信領域中,字符是一個信息單位,它是各種文字和符號的總稱,包括各國家文字、標點符號、圖形符號、數字等。比如,一個漢字,一個英文字母,一個標點符號等都是一個字符。
字符集(Character set)
字符集是字符的集合。字符集的種類較多,每個字符集包含的字符個數也不同。比如,常見的字符集有 ASCII 字符集、GB2312 字符集、Unicode 字符集等,其中,ASCII 字符集共有 128 個字符,包含可顯示字符(比如英文大小寫字符、阿拉伯數字)和控制字符(比如空格鍵、回車鍵);GB2312 字符集是中國國家標準的簡體中文字符集,包含簡化漢字、一般符號、數字等;Unicode 字符集則包含了世界各國語言中使用到的所有字符
字符編碼(Character encoding)
字符編碼,是指對於字符集中的字符,將其編碼爲特定的二進制數,以便計算機處理。常見的字符編碼有 ASCII 編碼,UTF-8 編碼,GBK 編碼等。一般而言,字符集和字符編碼往往被認爲是同義的概念,比如,對於字符集 ASCII,它除了有「字符的集合」這層含義外,同時也包含了「編碼」的含義,也就是說,ASCII 既表示了字符集也表示了對應的字符編碼。
常見字符編碼簡介:
常見的字符編碼有 ASCII 編碼,GBK 編碼,Unicode 編碼和 UTF-8 編碼等等。這裏,我們主要介紹 ASCII、Unicode 和 UTF-8。
ASCII
計算機是在美國誕生的,人家用的是英語,而在英語的世界裏,不過就是英文字母,數字和一些普通符號的組合而已。在 20 世紀 60 年代,美國製定了一套字符編碼方案,規定了英文字母,數字和一些普通符號跟二進制的轉換關係,被稱爲 ASCII (American Standard Code for Information Interchange,美國信息互換標準編碼) 碼。比如,大寫英文字母 A 的二進制表示是 01000001(十進制 65),小寫英文字母 a 的二進制表示是 01100001 (十進制 97),空格 SPACE 的二進制表示是 00100000(十進制 32)。
Unicode
ASCII 碼只規定了 128 個字符的編碼,這在美國是夠用的。可是,計算機後來傳到了歐洲,亞洲,乃至世界各地,而世界各國的語言幾乎是完全不一樣的,用 ASCII 碼來表示其他語言是遠遠不夠的,所以,不同的國家和地區又制定了自己的編碼方案,比如中國大陸的 GB2312 編碼 和 GBK 編碼等,日本的 Shift_JIS 編碼等等。雖然各個國家和地區可以制定自己的編碼方案,但不同國家和地區的計算機在數據傳輸的過程中就會出現各種各樣的亂碼(mojibake),這無疑是個災難。
怎麼辦?想法也很簡單,就是將全世界所有的語言統一成一套編碼方案,這套編碼方案就叫 Unicode,它爲每種語言的每個字符設定了獨一無二的二進制編碼,這樣就可以跨語言,跨平臺進行文本處理了,是不是很棒!
Unicode 1.0 版誕生於 1991 年 10 月,至今它仍在不斷增修,每個新版本都會加入更多新的字符,目前最新的版本爲 2016 年 6 月 21 日公佈的 9.0.0。
Unicode 標準使用十六進制數字,而且在數字前面加上前綴 U+,比如,大寫字母「A」的 unicode 編碼爲 U+0041,漢字「嚴」的 unicode 編碼爲 U+4E25。更多的符號對應表,可以查詢 unicode.org,或者專門的漢字對應表。
UTF-8
Unicode 看起來已經很完美了,實現了大一統。但是,Unicode 卻存在一個很大的問題:資源浪費。
爲什麼這麼說呢?原來,Unicode 爲了能表示世界各國所有文字,一開始用兩個字節,後來發現兩個字節不夠用,又用了四個字節。比如,漢字「嚴」的 unicode 編碼是十六進制數 4E25,轉換成二進制有十五位,即 100111000100101,因此至少需要兩個字節才能表示這個漢字,但是對於其他的字符,就可能需要三個或四個字節,甚至更多。
這時,問題就來了,如果以前的 ASCII 字符集也用這種方式來表示,那豈不是很浪費存儲空間。比如,大寫字母「A」的二進制編碼爲 01000001,它只需要一個字節就夠了,如果 unicode 統一使用三個字節或四個字節來表示字符,那「A」的二進制編碼的前面幾個字節就都是 0,這是很浪費存儲空間的。
爲了解決這個問題,在 Unicode 的基礎上,人們實現了 UTF-16, UTF-32 和 UTF-8。下面只說一下 UTF-8。
UTF-8 (8-bit Unicode Transformation Format) 是一種針對 Unicode 的可變長度字符編碼,它使用一到四個字節來表示字符,例如,ASCII 字符繼續使用一個字節編碼,阿拉伯文、希臘文等使用兩個字節編碼,常用漢字使用三個字節編碼,等等。
因此,我們說,UTF-8 是 Unicode 的實現方式之一,其他實現方式還包括 UTF-16(字符用兩個或四個字節表示)和 UTF-32(字符用四個字節表示)。
Python默認編碼:
Python2 的默認編碼是 ascii,Python3 的默認編碼是 utf-8,可以通過下面的方式獲取:Python2
Python 2.7.11 (default, Feb 24 2016, 10:48:05)
[GCC 4.2.1 Compatible Apple LLVM 7.0.2 (clang-700.1.81)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.getdefaultencoding()
'ascii'
Python3
Python 3.5.2 (default, Jun 29 2016, 13:43:58)
[GCC 4.2.1 Compatible Apple LLVM 7.3.0 (clang-703.0.31)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.getdefaultencoding()
'utf-8'
Python編碼歷史
由於Python創始人在開發初期的侷限性選擇了ASCII當做了默認編碼,導致其無法支持其他的國家的開發者的語言,當後來大家對支持漢字、日文、泰文等語言的呼聲越來越高時,Python於是準備引入unicode。但若直接把默認編碼改成unicode的話是不現實的, 因爲很多軟件就是基於之前的默認編碼ASCII開發的,改變編碼後以前的程序的編碼就都亂了,所以Python 2 就直接搞了一個新的字符類型,就叫unicode類型。
1、常見的編碼種類有:
ASCII 佔1個字節,只支持英文
GB2312 佔2個字節,支持6700+漢字
GBK GB2312的升級版,支持21000+漢字
Shift-JIS 日本字符
ks_c_5601-1987 韓國編碼
TIS-620 泰國編碼
Unicode 2-4字節 已經收錄136690個字符,並還在一直不斷擴張中...
2、Unicode 編碼
(1)直接支持全球所有語言,每個國家都可以不用再使用自己之前的舊編碼了,直接使用Unicode就可以了。(就跟英語是全球統一語言一樣)
(2)Unicode包含了跟全球所有國家編碼的映射關係Unicode解決了字符和二進制的對應關係,但是使用Unicode表示一個字符,太浪費空間(利用unicode表示“Python”需要12個字節才能表示,比原來ASCII表示增加了1倍)。
3、UTF 編碼
爲了解決存儲和網絡傳輸的問題,出現了Unicode Transformation Format,學術名UTF,即:對unicode中的進行轉換,以便於在存儲和網絡傳輸時可以節省空間!
UTF-8: 使用1、2、3、4個字節表示所有字符;優先使用1個字符、無法滿足則使增加一個字節,最多4個字節。英文佔1個字節、歐洲語系佔2個、東亞佔3個,其它及特殊字符佔4個
UTF-16: 使用2、4個字節表示所有字符;優先使用2個字節,否則使用4個字節表示。
UTF-32: 使用4個字節表示所有字符;
Python2編碼轉換過程
假如在文件要輸出中文字符串,但是手動聲明爲coding utf-8,解釋器會以聲明的編碼解釋代碼,加載至內存變量類型爲utf-8,顯示至windows(中國的windows,默認編碼依然是gbk)界面後是亂碼。有三種方法可以解決以上問題:
1、字符串以GBK格式顯示
2、字符串是unicode編碼
3、手動轉成unicode編碼
UTF-8 --> decode 解碼 --> Unicode
Unicode --> encode 編碼 --> GBK / UTF-8
Python3
1、解釋器找到代碼文件,把代碼字符串按文件頭定義的編碼加載到內存,轉成unicode
2、把代碼字符串按照語法規則進行解釋,
3、所有的變量字符都會以unicode編碼聲明
編碼出錯檢查步驟
1、Python解釋器的默認編碼
2、Python源文件文件編碼
3、Terminal使用的編碼
4、操作系統的語言設置