Unicode 標準描述了 ** 碼位(code point) ** 如何表示字符。一個碼位的值是在 0 到 0x10FFFF(大約 110 萬個值,目前有其中 11 萬個被指派)。在這一標準中,一個碼位寫作 U+265E 來表示擁有值 0x265e的字符(十進制下為 9,822)。
一個 Unicode 字符串是一系列碼位(從 0 到 0x10FFFF 或者說十進制的 1,114,111 的數(shù)字)組成的序列。這一序列在內(nèi)存中需要被表示為一組 ** 碼元 **,然后 ** 碼元 ** 會對應到包含八個二進制位的字節(jié)。將 Unicode 字符串翻譯成字節(jié)序列的規(guī)則被稱為 ** 字符編碼 **,或者 ** 編碼 **。
Python 的字符串類型使用 Unicode 標準來表示字符,這使 Python 程序能夠正常處理所有這些可能的字符。
UTF-8
UTF-8是最常用的編碼之一,Python通常默認使用它。UTF代表“Unicode”轉(zhuǎn)換格式”,而“8”表示在編碼中使用8位值。(還有UTF-16和UTF-32編碼,但使用頻率低于UTF-8。)UTF-8使用以下規(guī)則:
- 如果代碼點< 128,則由對應的字節(jié)值表示
- 如果代碼點是>= 128,那么它將被轉(zhuǎn)換成一個由兩個、三個或四個字節(jié)組成的序列,其中每個字節(jié)的長度在128到255之間。
UTF-8 is one of the most commonly used encodings, and Python often defaults to using it. UTF stands for ”UnicodeTransformation Format”, and the ’8’ means that 8-bit values are used in the encoding. (There are also UTF-16 andUTF-32 encodings, but they are less frequently used than UTF-8.) UTF-8 uses the following rules:
- If the code point is < 128, it’s represented by the corresponding byte value.
- If the code point is >= 128, it’s turned into a sequence of two, three, or four bytes, where each byte of thesequence is between 128 and 255.
UTF-8 編碼規(guī)則
UTF-8 是一個非常驚艷的編碼方式,漂亮的實現(xiàn)了對 ASCII 碼的向后兼容,以保證 Unicode 可以被大眾接受。
UTF-8 是目前互聯(lián)網(wǎng)上使用最廣泛的一種 Unicode 編碼方式,它的最大特點就是可變長。它可以使用 1 - 4 個字節(jié)表示一個字符,根據(jù)字符的不同變換長度。編碼規(guī)則如下:
對于單個字節(jié)的字符,第一位設為 0,后面的 7 位對應這個字符的 Unicode 碼點。因此,對于英文中的 0 - 127 號字符,與 ASCII 碼完全相同。這意味著 ASCII 碼那個年代的文檔用 UTF-8 編碼打開完全沒有問題。
對于需要使用 N 個字節(jié)來表示的字符(N > 1),第一個字節(jié)的前 N 位都設為 1,第 N + 1 位設為0,剩余的 N - 1 個字節(jié)的前兩位都設位 10,剩下的二進制位則使用這個字符的 Unicode 碼點來填充。
根據(jù)上面編碼規(guī)則對照表,進行 UTF-8 編碼和解碼就簡單多了。下面以漢字“漢”為利,具體說明如何進行 UTF-8 編碼和解碼。
“漢”的 Unicode code point 是 0x6c49(110 1100 0100 1001),通過上面的對照表可以發(fā)現(xiàn),0x0000 6c49 位于第三行的范圍,那么得出其格式為 1110xxxx 10xxxxxx 10xxxxxx。接著,從“漢”的二進制數(shù)最后一位開始,從后向前依次填充對應格式中的 x,多出的 x 用 0 補上。這樣,就得到了“漢”的 UTF-8 編碼為 11100110 10110001 10001001,轉(zhuǎn)換成十六進制就是 0xE6 0xB7 0x89。
解碼的過程也十分簡單:如果一個字節(jié)的第一位是 0 ,則說明這個字節(jié)對應一個字符;如果一個字節(jié)的第一位1,那么連續(xù)有多少個 1,就表示該字符占用多少個字節(jié)。
總結(jié)
UTF-8,UTF-16,UTF-32 此類編碼方式不同 指的是將Unicode code point 的十六進制數(shù)如何轉(zhuǎn)換成機器存儲的二進制數(shù)的 轉(zhuǎn)換規(guī)則不同。而不是將code point 直接轉(zhuǎn)換成32位的二進制數(shù)進行編碼和解碼的。與ASCII碼編碼方式不同
Unicode字符集 與 ASCII 字符集 兼容。正是因為UTF-8的這種可變長度字節(jié)的規(guī)則,將127個ASCII字符放在里Unicode 字符集的前127個區(qū)位,使得二進制數(shù)值與code point 剛好吻合。
GBK、各個國家的字符集只是對ASCII的擴展,但是相互之間并不通用,字符集和編碼方式各不相同。