標籤:

字元編碼:計算機的巴別塔

本文是飢人谷學員的博客,原載於 henggs Blog

巴別塔:《聖經·舊約·創世記》第11章宣稱,當時人類聯合起來興建希望能通往天堂的高塔;為了阻止人類的計劃,上帝讓人類說不同的語言,使人類相互之間不能溝通,計劃因此失敗,人類自此各散東西。此故事試圖為世上出現不同語言和種族提供解釋。

我們曾經在HTTP的響應頭中見到過Content-Type:text/html; charset=utf-8,也曾在HTML文件中見到過<meta charset="utf-8">。它們都是用於聲明字元編碼為utf-8。那麼utf-8到底是什麼?這要從計算機的起源說起。

最早的計算機是機械式繼電器計算機,通過繼電器的開關狀態來表示0和1。後來的電子管計算機、晶體管計算機、集成電路計算機都繼承了這一設定,這也是為什麼計算機以二進位來存儲數據。

人類發明計算機的目的是處理數據,而絕大多數數據都是文本形式的,所以要把這些文本轉換為計算機可識別的二進位數據,再把計算機處理過的二進位數據轉換為人類可識別的文本。這個二進位和文本的對照表就是字符集。

ASCII

美國人發明了最早的現代計算機。所以美國人最初制定了ASCII(American Standard Code for Information Interchange,美國信息互換標準代碼)來保存控制碼、空格、標點符號、數字、大小寫字母。計算機的一個位元組可以組合出2^8種不同的狀態。 ASCII使用了128個狀態。

編號從0開始的32種狀態分別規定了特殊的用途,這些0×20以下的位元組狀態稱為」控制碼」。

隨著世界各地的不同國家開始使用計算機,為了可以在計算機中使用ASCII中沒有制定的文字,在128至255號之後的狀態來表示這些新的字母、符號。這些字符集被稱「擴展字符集」。

GB2312、GBK和BIG5

ASCII中是沒有漢字的,而常用簡體漢字就有幾千個。所以中國制定了GB2312(GB是國標的拼音縮寫)。GB2312規定:一個小於127的字元的意義與原來相同,但兩個大於127的字元連在一起時,就表示一個漢字。GB2312收錄了6763個常用漢字。這也是為什麼在以前一個漢字算兩個英文字元的原因。

但是漢字有那麼多,GB2312中並不包含生僻字,所以還是需要擴展。擴展之後的編碼方案被稱為GBK標準,GBK包括了GB2312的所有內容,同時又增加了近20000個新的漢字(包括繁體字)和符號。

當時同文同種的港台同胞們也制定一套編碼標準BIG5,這套標準和GB2312/GBK並不兼容。而世界各地其他國家也制定了自己的標準。雖然本地使用沒有問題,然而在網路中由於字符集不兼容,大家誰也看不懂別人的編碼,互相訪問就會出現亂碼。我們彷彿進入了巴別塔被摧毀後的世界。

unicode

為解決這個問題,ISO(國際標誰化組織)制定了通用字符集:「Universal Multiple-Octet Coded Character Set」,簡稱UCS,又稱unicode。

ISO規定必須用4個位元組來統一表示所有的字元,對於ASCII里的那些「半形」字元,unicode包持其原編碼不變,只是將其長度由原來的8位擴展為32位,高位全部置為0,而其他語言的字元則全部重新統一編碼。這個字符集的編碼方式稱為UTF-32(32-bit UCS Transfer Format)。人類通過unicode建立了計算機世界的巴別塔。

有2^32個狀態的unicode以後會不會也不夠用?以前我們還覺得IPv4的地址用不完呢。

但人類之所以偉大,原因之一就在於我們能夠通過無窮的創造力解決各種問題。

如果按照unicode規定,每個符號用4個位元組表示,那麼文本文件的大小會因此大出二三倍,在存儲和傳輸上就會很浪費。這也是unicode在很長一段時間內無法推廣的原因。

UTF-8

直到UTF-8的出現。UTF-8(8-bit Unicode Transformation Format)是一種針對unicode的可變長度字元編碼。它可以用來表示unicode標準中的任何字元,且其編碼中的第一個位元組仍與ASCII兼容,這使得原來處理ASCII字元的軟體無須或只須做少部份修改,即可繼續使用。因此,它逐漸成為電子郵件、網頁及其他存儲或傳送文字的應用中優先採用的編碼。互聯網工程工作小組(IETF)要求所有互聯網協議都必須支持UTF-8編碼。

UTF-8使用一至四個位元組為每個字元編碼:

unicode是字符集,UTF-8是這一字符集的編碼方式。

  • 單位元組的字元,位元組的第一位設為0,對於英語文本,UTF-8碼只佔用一個位元組,和ASCII碼完全相同;
  • n個位元組的字元(n>1),第一個位元組的前n位設為1,第n+1位設為0,後面位元組的前兩位都設為10,這n個位元組的其餘空位填充該字元unicode碼,高位用0補足。

這樣就形成了如下的UTF-8標記位:

  • 0xxxxxxx
  • 110xxxxx 10xxxxxx
  • 1110xxxx 10xxxxxx 10xxxxxx
  • 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
  • 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
  • 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx

全文完。

推薦閱讀:

meta標籤
從零開始如何系統學好前端開發基礎?
記錄weasyprint在window10+python3的安裝
淺析瀏覽器輸入URL到頁面輸出執行流程
html自閉合標籤加斜杠問題?

TAG:前端开发 | HTML |