UTF-8 簡史

Unicode,UCS,UTF淵源太深,一篇文章恐怕講不完,這裏只說UTF-8.html

0. Character Set & Encoding Form

先作一個小說明,一般咱們說到Unicode, UCS, UCS-2, UCS-4, UTF-8, UTF-16, UTF-32時,很容易混淆其概念,有必要作一個區分. 網絡

Unicode和UCS是一種字符集,它定義了每個抽象字符與數字的對應關係.它就像一張表格,上面數字與字符一一對應,告訴你1表明什麼,2表明什麼,3表明什麼,如此...這是一種映射關係,無關乎具體字符是怎麼樣存儲在電腦中的; 而關於如何存儲,這就是UCS-2,UCS-4,UTF-8,UTF-16,UTF-32的事兒了,它告訴你每個字符以多少個字節表明,字符所對應的數字是直接轉換爲其對應的2進制仍是通過必定的編碼轉換存儲起來. 用官方的術語來講Unicode,UCS是Character Set; UCS-2, UCS-4, UTF-8, UTF-16, UTF-32是Encoding Form.編碼

有關講述字符集及其編碼形式的文章,網上一搜一大堆,這裏就再也不贅述,本文只把重點放在UTF-8的由來.設計

1. 由來

1.1 UTF-8以前

UTF-8出現以前,處理多語言字符集時可能是用的雙字節序來編碼存儲字符.什麼是雙字節序?UCS-2,UTF-16就是雙字節序,它們使用兩個字節表示一個字符(UTF-16會使用到4個字節編碼一個字符,即兩個雙字節爲一個編碼),那個時候UCS與Unicode仍是各自獨立的字符集標準,雙方委員會所制定標準時還有很多差別,不過兩個標準所定義的字符範圍都未超過[0x0000, 0xFFFF]這個區間,因而16位(雙字節)足以表示全部字符.code

UTF-8的創造者Rob Pike與Ken Thompson大犇那個時候也在用ISO/IEC 10646(UCS)所定義的雙字節編碼來處理文本.按照他們的話來講orm

We hate it!htm

這種編碼有不少問題,其中最要緊的兩個問題就是,在文本中雙字節會產生錯誤的NULL(\0)邊界,以及在文件系統中,一個使用雙字節表示的斜線(/)很難判斷其路徑是否結束,它很難兼容單字節編碼系統.ip

1.2 The Phone Call

直到1992年9月的某一天晚上,Rob Pike接到一個電話,是18M的一個工做小組打來的,他們想讓Rob Pike和Ken Thompson審閱一份由他們起草的變長字符編碼提案,那會Ken Thompson就在Rob旁邊,收到提案後他們立馬研究起來,他們發現這份提案中解決了許多(包括上面提到的兩個)雙字節編碼面臨的問題,還可以完美的兼容US-ASCII,也就是說它可以兼允許多單字節編碼系統,提案將這種編碼命名爲FSS-UTF.這看上去這份提案十分使人滿意,但是Rob和Ken並無知足,由於在他們心中,這個提案至少還有一個問題沒有解決.utf-8

這種編碼在存儲,處理和轉換上表現得都很不錯,但是在傳輸過程當中,無法作到自描述邊界.換句話說,計算機在接收來自網絡的字符數據時,不經過上下文就沒法知道當前接收的這個字節是上一個字符的一部分仍是新的字符的開始,這會給字符拼接帶來難度和效率上的開銷,要作到這一點,就必須進一步改進.unicode

Rob和Ken馬上意識到他們有機會在此基礎上設計一種更完美的字符編碼系統.那天晚餐事後,他們開始着手修改這個設計中缺陷的部分.很快,他們就完成了設計,並將這份修改提案回發給了18M小組,收到提案的小組很快做出了回覆,他們一致認爲這份修改比原始的那一份更優秀.通過確認後,Rob和Ken開始着手編寫編碼裝換程序與C語言庫,到了次日,代碼已經能在機器上跑起來了.這個修改提案即是UTF-8的由來.後來18M小組把這份修改後的FSS-UTF提案提交了,這就有了後來被誤解爲18M設計了UTF-8,固然再後來Rob和Ken發表了一篇paper正式介紹了UTF-8(見文章結尾參考),paper裏將其稱做UTF-2,而後通過漫長的標準化,最後UTF-8的名字得意肯定,固然那是後來的事了.

要理解Rob和Ken在這份提案中作了什麼樣的修改使得這個編碼系統設計的更加完美,咱們先來看看原版FSS-UTF的設計,在引入變長編碼方案時,FSS-UTF與UTF-8在處理首字節的作法很相近,都是在高位1的數目來描述一個字符編碼所佔字節長度(須要對UTF-8編碼方式有了解):

字節長度 FSS-UTF UTF-8
1 0xxxxxxx 0xxxxxxx
2 10xxxxxx 1xxxxxxx 110xxxxx 10xxxxxx
3 110xxxxx 1xxxxxxx 1xxxxxxx 1110xxxx 10xxxxxx 10xxxxxx
4 1110xxxx 1xxxxxxx 1xxxxxxx 1xxxxxxx 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
5 11110xxx 1xxxxxxx 1xxxxxxx 1xxxxxxx 1xxxxxxx 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
6 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx

以上表格中,x爲任意二級制值,咱們能夠看出,FSS-UTF設計問題就在於當字符是多字節時,非首字節部分沒法表達自身是非首字節.例如,在傳輸過程當中,傳遞一個雙字節的FSS-UTF編碼: 10111111 10111111,這顯然是一個有效FSS-UTF編碼,但它的第二個字節自己是沒法自描述,這就形成了字符在網絡傳輸過程當中很難容錯.

而UTF-8就完美的解決了這個問題,由於對於任何長度的編碼,首字節高2位是毫不可能出現10這個特徵值的,因此在傳輸過程當中,接收方只要發現當前接收字節爲10xxxxxx,即可知道它是上一個未傳完字符的一部分,若是以其餘非10xxxxxx形式,即可知道它是新字符的首字節.這樣就完美的解決了問題.

2. 有關UTF-8的趣事

關於UTF,其實有兩個解釋,一個是UCS Transformation Format,另外一個是Unicode Transformation Format.爲何會有兩個?

這是由於當初UTF-8有兩種實現,一個是做爲UCS的實現,當時UCS的字符編碼範圍是[0x00000000, 0x7FFFFFFF]整整31位,這就是上面表格所看到的UTF-8的編碼規則,若是你仔細數一下x的個數,你就會發現正好是31個,這種最高6個字節的UTF-8編碼就是當時針對UCS字符集的實現,熟悉UTF-8的人剛看到上面表格中的定義可能會詫異甚至反對,由於如今的UTF-8編碼規定了只佔4個字節,這就跟第二種實現有關了.

這第二種實現是針對Unicode的,自從Unicode 3.1開始將其編碼範圍調整到[0x000000, 0x10FFFF]整整21位,所以依照上面的表格,數一數4個字節的UTF-8編碼x的個數,也是21個.

後來ISO/IEC 10646與Unicode的標準委員會決定統一併同步兩種字符集的更新,ISO/IEC 10646承諾再也不分配21位以上的字符空間,因而兩種UTF-8變成了一回事.所以有了這麼一個有趣的事實,標準中仍然將UTF採用原先的命名即UCS Transformation Format,但在這份標準文件中又將Unicode的UTF-8實現作爲權威參考,因此今天咱們能夠說的UTF-8指的就是Unicode Transformation Format-8.另外兩種規範的統一又使得UCS-4與UTF-32變成了一回事.

3. 參考

UTF-8, a transformation format of ISO 10646
UTF-8 history
UTF-8 and Unicode FAQ for Unix/Linux
UTF-8 Wikipedia

相關文章
相關標籤/搜索