大神解惑|為什么要用UTF-8

小白在學習 Python 中的“字符串”這個基本概念時,問了大神這樣一個問題:既然 Python 內部的字符串都是使用 Unicode 來編碼的,那干嘛還要在存儲和傳輸的時候轉成 UTF-8 呢?這樣轉來轉去的多麻煩?

說實話,回答小白的問題,通常比回答大神的問題要難。因為他們總是問一些不著邊際的問題。好在偉大的互聯網時代,沒有什么事情不可以通過在網上搜集信息,整理分析之后給出一個相對滿意的回答的。

小白提出這個問題,主要是源于網上教程中一個錯誤的解釋:Unicode標準也在不斷發展,但最常用的是用兩個字節表示一個字符(如果要用到非常偏僻的字符,就需要4個字節)。于是,小白就認為,既然2個字節可以搞定,干嘛還搞成 UTF-8,因為那樣可能需要 3 個字節或者更多來表示一個字。這里的錯誤是什么呢?就是混淆了“標準”和“實現”。好吧,小白肯定又要暈了。

先來舉一個現實中的例子:現在我們使用的長度單位是“米”。這就是一個標準。這個標準怎么定義的呢?在國際計量學會有幾個標準“米”容器,那個東西的長度,就被定義成一個標準的“米”。但不會有誰真的跑去用那個標準容器。我們都是以那個標準容器為樣板,生產自己的尺,來測量東西。這個尺就是“米”這個標準的一種實現。我們可以做一根硬的木尺,也可以是軟的卷尺,還可以是使用激光測距的光尺。不管怎么說,只要這個尺量出來的“米”和標準容器量出來的“米”是一樣的,那就可以了。

那么 Unicode 是怎么回事呢?Unicode 做為一個國際標準,其實只是定義了每個字符對應的一個數字(實際上 Unicode 包含很多復雜的內容,這里只說最簡單的部分),比如 20031 這個數字就代表“中”這個字,25991 代表“文”這個字。但其實 Unicode 并沒有說你要怎么保存一個字。

現在大家都知道,電腦里存信息,通常使用的單位叫:字節。比如我們說一首歌下載需要 3MB 的流量,翻譯成“人話”,就是需要傳輸 3 百萬字節的信息。一個字節能表示的數字非常的少,只能表示 0 - 255 這 256 個數。那如果我們需要表示超過 255 的數字要怎么辦?那當然就是用多個字節。比如兩個字節就可以表示 0 - 65535 這 65536 個數了。那我要表示負數怎么辦?最笨的辦法就是用3個字節嘛,用一個字節來表示正負,剩下的字節來表示數字。當然小白肯定會說:正負就兩個狀態,需要一個字節,那多浪費!于是,有就了各種不使用3個字節也能表示正負數的方法。這部分內容,任何一本“計算機原理”的書里都會講到。什么符號位啊,補碼啊……

講這么一堆關于怎么表示一個數字的問題干什么呢?和這里說的 Unicode 和 UTF-8 有什么關系呢?當然有關系!這里大神要說的意思就是:同樣一個數,你可以選不同的方式來表示它(比如剛才說的用3個字節來表示正負數,或者使用符號位來表示正負數)。選用什么方案,就是對 Unicode 的一種編碼方法,也就是我們剛才說的“實現”。為什么前面提到的教程作者會說 Unicode 通常是兩個字節呢?因為在 Unicode 早期,設計 Unicode 的人學識有限。他們在考查了世界上主要的文字之后,感覺用2個字節也就是最多 65536 個字符應該夠用了。對應于一種 2 字節的編碼方案叫 UCS2。后來做著做著,發現不對了,2個字節不夠用了(現在 Unicode 包含了 12萬 8 千個字符),又擴展到4個字節(因為計算機使用二進制的原因,3個字節在讀寫的時候很沒效率,所以都是2的倍數來擴展的),對應于一種編碼方案叫 UCS4。而對于我們來說,常用的中文字都在 65535 以下,所以通常 UCS2 就能表示常用的 6000 多個漢字了。這里說的 UCS2 和 UCS4 都是 Unicode 的“實現”,或者叫編碼方案。雖然,因為 UCS2 不能覆蓋全部的 Unicode 字符集,已經被標為“廢棄”了,但不要被他們騙了,一個已經使用了很久的技術,想廢棄是非常難的。

UCS2 和 UCS4 都是固定編碼長度的方案。也就是說不管是什么字符,都使用 2 個字節或者 4 個字節來表示。對于我們來說,這并不是什么問題,但問題出在:這個世界上最流行的語言不是漢語,而是英語(中國人表示不服!漢語是世界上使用人數最多的語言)。雖然把每個英語字母都使用兩個字節來表示也不是什么大的問題,可是,在遙遠的計算機啟蒙時代,無論是硬盤的大小還是網絡的速度,都非常的有限,如果不對傳輸的內容進行壓縮和限制,那成本是非常高的。于是就有了 UTF-8。

和 UCS2 這樣的固定編碼長度的方案不同的的是,UTF-8 并不是固定長度的。最短的 UTF-8 字符只需要使用 1 個字節。最長是 5 個字節。最長那 5 個字節能表示的數字,相當于用 4 個連續字節用來表示正負數,里面正數的個數,大概有20多億,具體是多少,其實也不重要??雌饋?,多用了一個字節,還沒有原來表示的數字多,好像很浪費,但這里的目的是:最常用的英文字母,使用最少的字節,不常用的,反正也不常用,多兩個字節沒關系。(這里請不要批判帝國主義霸權。不是人家想把英文搞這么短,是我們的中文想搞短也做不到……)

說回 Python。在 Python 3.3 版之后,對內部的 str 表示做了一些改進。教程里說:Python 內部使用 Unicode 來表示字符串,而在保存到硬盤或者發送到網上,需要轉成 UTF-8。這個說法其實不夠準確。在 Python 內部(不同的版本可能不同,大神在這里引用的是 Python 3 的文檔),是使用 UCS 的各種版本來表示字符串的。比如說,對整個字符串做一次掃描,發現所有的字符都小于 255,那么就使用 UCS1,也就是一個字節的編碼方案;如果發現有大于 255 的字符,但又都小于 65535,那么就使用 UCS2。當然,如果發現有奇怪的字符,那就只能使用 UCS4 了。為什么在內部要使用 UCS 呢?怎么不繼續使用 UTF-8,那樣不就不用轉換了嗎?(小白總是想省事)這個就涉及到 UTF-8 的一個缺點:計算字符串長度和查找子字符串非常沒效率。在使用 UCS2 的時候,要想知道這個字符串有多長,只要看一下它占了幾個字節,然后除個 2 就可以了,而 UTF-8 的話,就需要一個字符一個字符的數出來。在做子字符串搜索的時候,因為不知道下一個字符占幾個字節,所以那些高效的搜索算法也都不靈了(小白:算法是啥?)。基于這兩個原因,只好做一個轉換:在保存到硬盤或網絡傳輸的時候,使用一種壓縮的方案,使得傳輸或保存需要的字節數最少;而在內部進行處理的時候,則使用效率更高的 UCS 方案。

PS:大神非常爽的講完之后,小白似懂非懂的走開了……

參考資料:

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,501評論 6 544
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,673評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 178,610評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,939評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,668評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 56,004評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,001評論 3 449
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,173評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,705評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,426評論 3 359
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,656評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,139評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,833評論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,247評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,580評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,371評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,621評論 2 380

推薦閱讀更多精彩內容

  • 字符集和編碼簡介 在編程中常??梢砸姷礁鞣N字符集和編碼,包括ASCII,MBCS,Unicode等字符集。確切的說...
    蘭山小亭閱讀 8,555評論 0 13
  • 可以看我的博客 lmwen.top 或者訂閱我的公眾號 簡介有稍微接觸python的人就會知道,python中...
    ayuLiao閱讀 3,145評論 1 5
  • 清晨的第一抹朝陽染紅海面天際 從遠處傳來的孤寺撞鐘聲 回蕩整個山谷 驚起了樹林中棲息的鴻雁 木魚打鳴聲中 掃地僧人...
    潁阿閱讀 307評論 4 16
  • 你最近的狀態怎么樣呀?渾渾噩噩,不知所措。似乎這樣消極的回答是我在與用戶進行交流溝通時聽到的最多的。然而一個人真的...
    王二道閱讀 426評論 0 0
  • ?無論友情還是愛情,你有被人堅定的選擇過嗎? 我相信每個人骨子里其實都是自私的,都希望自己擁有的愛是獨一無二的,是...
    米未閱讀 4,289評論 6 9