字符編碼的前世今生

  今天我們不談編程,來聊聊歷史(笑=-=)

  同學們請先思考一個問題:我們只有十支手指,那麼怎麼用這十支手指表示超過10的數呢?比如說23!

  ...

  在很久很久以前,在沒有文字的年代,老古人結繩計數,一個結代表一個數字!

  ...

  當年周幽王烽火戲諸侯,只是爲得美人一笑,我們就來聊一聊周幽王是怎麼想的(=-=!),古時候通信是最大的問題,打仗的時候通過烽火臺傳遞敵情。根據敵情的不同,有着不同的規定。如一道烽火代表500人以下,兩道代表500~1000,三道代表1000到5000.。。。依次類推。其實這就是進制的雛形,通過不同數位代表不同的權重,來表示更大的數據。

  不扯這些了,迴歸正題,現在的計算機仍然很弱小,你以爲計算機可以存儲成千上萬種的語言,你以爲計算機可以儲存任何文件,例如圖片、視頻,你以爲計算機可以做任何計算,其實不是這樣的,計算機要比我們想象中弱小的多,就算他再表現的強大,表現的更加人性化,他也只能認識0和1,只能處理二進制數據,這是我們站在現在的角度去思考前人處理問題的方式,現在我們站在前人的角度來想。1945年美國賓夕法尼亞大學的兩位教授-莫奇利和埃克特設計和研製出了世界上第一臺計算機ENIAC(電子數字積分計算機)。現在我們有了第一臺計算機,但是這個計算機只認識0和1,這就需要我們找到一個方法讓計算機“認識”其他數據,這就是編碼(英語:encode),通過編碼的方式將我們需要計算機認識的數據轉換爲二進制,讓計算機處理後,再解碼(英語:decode)呈現給我們,除了計算機設計工作人員,其他人一般不需要關心計算機是如何編碼和解碼的。

聲明:以下關於編碼的介紹轉自:騰訊遊戲官方設計團隊

ASCII

  8個晶體管的“通”或“斷”即可以代表一個字節,剛開始,計算機只在美國使用,所有的信息在計算機最底層都是以二進制(“0”或“1”兩種不同的狀態)的方式存儲,而8位的字節一共可以組合出256(2的8次方)種狀態,即256個字符,這對於當時的美國已經是足夠的了,他們嘗試把一些終端的動作、字母、數字和符號用8位(bit)來組合:

  • 0000 0000 ~ 0001 1111 共 33 種狀態用來表示終端的特殊動作,如打印機中的響鈴爲 0000 0111 ,當打印機遇到 0000 0111 這樣的字節傳過來時,打印機就開始響鈴;
  • 0010 0000 ~ 0010 1111 、 0011 1010~0110 0000 和 0111 1101 ~ 0111 1110 共 33 種狀態來表示英式標點符號,如 0011 1111 即代表英式問號“?”;
  • 0011 0000 ~ 0011 1001 共 10 種狀態來表示“0~9”10個阿拉伯數字;
  • 0100 0001 ~ 0101 1010 和 0110 0001 ~ 0111 1010共 52種狀態來表示大小寫英文字母;

  自此,一共只用到了128種狀態,即128個字符,剛好佔用了一個字節中的後7位,共包括33個控制字符和95個可顯示字符,這一字符集被稱爲ASCII(American Standard Code for Information Interchange,美國信息交換標準代碼,這一套字符集在1967年被正式公佈。

講到這裏,引出幾個基礎概念:

  • 比特(bit):也可稱爲“位”,是計算機信息中的最小單位,是 binary digit(二進制數位) 的 縮寫,指二進制中的一位
  • 字節(Byte):計算機中信息計量的一種單位,一個位就代表“0”或“1”,每8個位(bit)組成一個字節(Byte)
  • 字符(Character):文字與符號的總稱,可以是各個國家的文字、標點符號、圖形符號、數字等
  • 字符集(Character Set):是多個字符的集
  • 編碼(Encoding): 信息從一種形式或格式轉換爲另一種形式的過程
  • 解碼(decoding): 編碼的逆過程
  • 字符編碼(Character Encoding): 按照何種規則存儲字符

現在我們來看我們文章開頭提到的第一條電報的誕生,莫爾斯編碼中包含了大小寫英文字母和數字等符號。

  • 這裏的每一個符號其實就是⌈字符⌋
  • 而這所有的字符的集合就叫做⌈字符集⌋
  • “點”或“劃”與字符之間的對應關係即可以稱爲⌈字符編碼⌋

而電報的原理是:

“點”對應於短的電脈衝信號,“劃”對應於長的電脈衝信號,這些信號傳到對方,接收機把短的電脈衝信號翻譯成“點”,把長的電脈衝信號轉換成“劃”,譯碼員根據這些點劃組合就可以譯成英文字母,從而完成了通信任務。
  • 這裏把字符表示爲“點”或“劃”並對應爲電脈衝信號的過程既是⌈編碼⌋
  • 而譯碼員把接收機接收到的脈衝信號轉化成點劃後譯成字符的過程即爲⌈解碼⌋

而對於計算機誕生之後,只不過是將摩斯電碼中的“點”和“劃”換成了以8位字節二進制流的方式表示,如數字1的二進制流是0011 0001,對應的十進制流是49,十六進制流是31。

EASCII

  雖然剛開始計算機只在美國使用,128個字符的確是足夠了,但隨着科技驚人的發展,歐洲國家也開始使用上計算機了。不過128個字符明顯不夠呀,比如法語中,字母上方有注音符號,於是,一些歐洲國家就決定,利用字節中閒置的最高位編入新的符號。比如,法語的é的二進制流爲1000 0010,這樣一來,這些歐洲國家的編碼體系,可以表示最多256個字符了。 但是,這裏又出現了新的問題。不同的國家有不同的字母,因此,哪怕它們都使用256個符號的編碼方式,代表的字母卻不一樣。比如,1000 0010在法語編碼中代表了é,在希伯來語編碼中卻代表了字母Gimel (?),在俄語編碼中又會代表另一個符號。但是不管怎樣,所有這些編碼方式中,0--127表示的符號是一樣的,不一樣的只是128--255的這一段。 EASCIIExtended ASCII,延伸美國標準信息交換碼)由此應運而生,EASCII碼比ASCII碼擴充出來的符號包括表格符號、計算符號、希臘字母和特殊的拉丁符號:

GB2312

  EASCII碼對於部分歐洲國家基本夠用了,但過後的不久,計算機便來到了中國,要知道漢字是世界上包含符號最多並且也是最難學的文字。 據不完全統計,漢字共包含了古文、現代文字等近10萬個文字,就是我們現在日常用的漢字也有幾千個,那麼對於只包含256個字符的EASCII碼也難以滿足天朝的需求了。 於是⌈中國國家標準總局⌋(現已更名爲⌈國家標準化管理委員會⌋)在1981年,正式制訂了中華人民共和國國家標準簡體中文字符集,全稱信息交換用漢字編碼字符集·基本集》,項目代號爲GB 2312 或 GB 2312-80(GB爲國標漢語拼音的首字母),此套字符集於當年的5月1日起正式實施。

  •   包含字符:共包含7445個字符,6763個漢字和682個其他字符(拉丁字母、希臘字母、日文平假名及片假名字母、俄語西裏爾字母)

  •   存儲方式:基於EUC存儲方式,每個漢字及符號以兩個字節來表示,第一個字節爲“高位字節”,第二個字節爲“低位字節”

BIG5

  要知道港澳臺同胞使用的是繁體字,而中國大陸制定的GB2312編碼並不包含繁體字,於是信息工業策進會在1984年與臺灣13家廠商簽定“16位個人電腦套裝軟件合作開發(BIG-5)計劃”,並開始編寫並推出BIG5標準。 之後推出的倚天中文系統則基於BIG5碼,並在臺灣地區取得了巨大的成功。在BIG5誕生後,大部分的電腦軟件都使用了Big5碼,BIG5對於以臺灣爲核心的亞洲繁體漢字圈產生了久遠的影響,以至於後來的window 繁體中文版系統在臺灣地區也基於BIG5碼進行開發。

  包含字符:共收錄13,060個漢字及441個符號

  編碼方式:用兩個字節來爲每個字符編碼,第一個字節稱爲“高位字節”,第二個字節稱爲“低位字節”

Unicode

由來:

在計算機進入中國大陸的相同時期,計算機也迅速發展進入了世界各個國家。 特別是對於亞洲國家而言,每個國家都有自己的文字,於是每個國家或地區都像中國大陸這樣去制定了自己的編碼標準,以便能在計算機上正確顯示自己國家的符號。 但帶來的結果就是國家之間誰也不懂別人的編碼,誰也不支持別人的編碼,連大陸和臺灣這樣只相隔了150海里,都使用了不同的編碼體系。 於是,世界相關組織意識到了這個問題,並開始嘗試制定統一的編碼標準,以便能夠收納世界所有國家的文字符號。 在前期有兩個嘗試這一工作的組織:

  • 國際標準化組織(ISO)
  • 統一碼聯盟

國際標準化組織(ISO)及國際電工委員會(IEC)於1984年聯合成立了ISO/IEC小組,主要用於開發統一編碼項目; 而Xerox、Apple等軟件製造商則於1988年組成了統一碼聯盟,用於開發統一碼項目。 兩個組織都在編寫統一字符集,但後來他們發現各自在做相同的工作,同時世界上也不需要兩個不兼容的字符集,於是兩個組織就此合併了雙方的工作成果,併爲創立一個單一編碼表而協同工作。

1991年,兩個組織共同的工作成果Unicode 1.0正式發佈,不過Unicode 1.0並不包含CJK字符(即中日韓)。

  • Unicode 1.0:1991年10月
  • Unicode 1.0.1:1992年6月
  • Unicode 1.1:1993年6月
  • Unicode 2.0:1997年7月
  • Unicode 2.1:1998年5月
  • Unicode 2.1.2:1998年5月
  • Unicode 3.0:1999年9月
  • Unicode 3.1:2001年3月
  • Unicode 3.2:2002年3月
  • Unicode 4.0:2003年4月
  • Unicode 4.0.1:2004年3月
  • Unicode 4.1:2005年3月
  • Unicode 5.0:2006年7月
  • Unicode 5.1:2008年4月
  • Unicode 5.2:2009年10月
  • Unicode 6.0:2010年10月
  • Unicode 4.1:2005年3月
  • Unicode 6.1:2012年1月31日
  • Unicode 6.2:2012年9月

ISO/IEC 8859

ISO/IEC小組在1984年成立後的第三年(即1987年)開始啓動ISO 8859標準的編寫,ISO 8859是一系列8位字符集的標準,主要爲世界各地的不同語言(除CJK)而單獨編寫的字符集,一共定義了15個字符集:

  • ISO/IEC 8859-1:西歐語言
  • ISO/IEC 8859-2  :中歐語言
  • ISO/IEC 8859-3 :南歐語言
  • ISO/IEC 8859-4: 北歐語言
  • ISO/IEC 8859-5: 斯拉夫語
  • ISO/IEC 8859-6: 阿拉伯語
  • ISO/IEC 8859-7:希臘語
  • ISO/IEC 8859-8:希伯來語
  • ISO/IEC 8859-9:土耳其語
  • ISO/IEC 8859-10: 北日耳曼語
  • ISO/IEC 8859-11:泰語
  • ISO/IEC 8859-13: 波羅的語族
  • ISO/IEC 8859-14: 凱爾特語族
  • ISO/IEC 8859-15:西歐語言,收錄芬蘭語字母和大寫法語重音字母,以及歐元(€)符號
  • ISO/IEC 8859-16 :東南歐語言,主要供羅馬尼亞語使用,並加入歐元(€)符號

其中ISO/IEC 8859-1至ISO/IEC 8859-4四個項目早在1982年就已經編寫出來,只不過是由ANSI與ECMA合作完成,並於1985年正式公佈,ISO/IEC小組成立後,這一成果被其收錄,並改名爲ISO/IEC 8859 前四個項目。 大家其實發現以上15個字符集中並沒有代號爲“ISO/IEC 8859 -12”的字符集,據說-12號本來是預留給印度天城體梵文的,但後來卻擱置了(阿三有了自己的編碼-ISCII)。由於英語沒有任何重音字母,故可使用以上十五個字符集中的任何一個來表示。

 ISO/IEC 10646 / UCS

1993年,ISO/IEC 10646標準第一次發表,ISO/IEC 10646是ISO 646的擴展,定義了1個31位的字符集。ISO 10646標準中定義的字符集爲UCS,UCS是Universal Character Set的縮寫,中文譯作通用字符集。

版本:

  • ISO/IEC 10646-1:第一次發表於1993年,現在的公開版本是2000年發表的ISO/IEC 10646-1:2000。
  • ISO/IEC 10646-2:在2001年發表。

包含字符:

最初的ISO 10646-1:1993的編碼標準,即Unicode 1.1,收錄中國大陸、臺灣、日本及韓國通用字符集的漢字共計20,902個,當然每個版本的Unicode標準的字符集所包含的字符數不盡相同,UCS包含了已知語言的所有字符,除了拉丁語、希臘語、斯拉夫語、希伯來語、阿拉伯語、亞美尼亞語、格魯吉亞語,還包括中文、日文、韓文這樣的方塊文字,此外還包括了大量的圖形、印刷、數學、科學符號。 UCS給每個字符分配一個唯一的代碼,並且賦予了一個正式的名字,通常在表示一個Unicode值的十六進制數的前面加上“U+”,例如“U+0041”代表字符“A”。

編碼方案:

UCS僅僅是一個超大的字符集,關於UCS制定的編碼方案有兩種:UCS-2UCS-4,Unicode默認以UCS-2編碼。 顧名思義,UCS-2就是用兩個字節編碼,UCS-4就是用4個字節(實際上只用了31位,最高位必須爲0)編碼。那麼UCS-2其實可以容納的字符數爲65536(2的16次方),而UCS-4可以容納的字符數爲2147483648(2的31次方)。其實對於UCS-2已經是完全夠用了,基本可以包含世界所有國家的常用文字,如果需要考慮一些偏僻字,那麼UCS-4則絕對可以滿足了,21億個字符哪怕是整個宇宙也夠用了吧!

UTF

Unicode 誕生,隨之而來的計算機網絡也發展了起來,Unicode 如何在網絡上傳輸也是一個必須考慮的問題,於是在1992年,面向網絡傳輸的UTF標準出現了。 UTF是Unicode Transformation Format的縮寫,中文譯作Unicode轉換格式。其實我們從現在可以把Unicode看作是一個標準或組織,而UCS就是一個字符集,那麼UCS在網絡中的傳輸標準就是UTF了。 前面提到了UCS的編碼實現方式爲UCS-2和UCS-4,即要麼是每個字符爲2個字節,要麼是4個字節。如果一個僅包含基本7位ASCII字符的Unicode文件,每個字符都使用2字節的原Unicode編碼傳輸,其第一字節的8位始終爲0,這就造成了比較大的浪費。但是,聰明的人們發明了UTF-8,UTF-8採用可變字節編碼,這樣可以大大節省帶寬,並增加網絡傳輸效率。

UTF-8

使用1~4個字節爲每個UCS中的字符編碼:

  • 128個ASCII字符只需一個字節編碼(Unicode範圍由U+0000至U+007F)
  • 拉丁文、希臘文、西裏爾字母、亞美尼亞語、希伯來文、阿拉伯文、敘利亞文及它拿字母需要二個字節編碼(Unicode範圍由U+0080至U+07FF)
  • 大部分國家的常用字(包括中文)使用三個字節編碼
  • 其他極少使用的生僻字符使用四字節編碼

UTF-16/UCS-2

UCS-2的父集,使用2個或4個字節來爲每個UCS中的字符編碼:

  • 128個ASCII字符需兩個字節編碼
  • 其他字符使用四個字節編碼

UTF-32/UCS-4

等同於UCS-4,對於所有字符都使用四個字節來編碼

GB13000

前面提到了Unicode的迅速發展,至1993年時,包含CJK的Unicode 1.1已經發布了,天朝的ZF也意識到了需要一個更大的字符集來走向世界,於是在同一年,中國大陸制定了幾乎等同於Unicode1.1的GB13000.1-93國家編碼標準(簡稱GB13000)。是的,你沒聽錯,中華人民共和國信息產業部把Unicode裏的所有東東拿過來,然後自己重新修訂發佈了下,改爲了國家標準GB13000。此標準等同於 ISO/IEC 10646.1:1993和Unicode 1.1。

GBK

1995年,在GB13000誕生後不久,中國教育科研網(NCFC)與美國NCFnet直接聯網,這一天是中國被國際承認爲開始有網際網路的時間。此後網絡正式開始在中國大陸接通,個人計算機開始在中國流行,雖然當時只是高富帥才消費得起的產品。中國是一個十幾億人口的大國,微軟意識到了中國是一個巨大的市場,當時的微軟也將自己的操作系統市場佈局進中國,進入中國隨之而來要解決的就是系統的編碼兼容問題。 之前的國家編碼標準GB 2312,基本滿足了漢字的計算機處理需要,它所收錄的漢字已經覆蓋中國大陸99.75%的使用頻率。但對於人名、古漢語等方面出現的罕用字和繁體字,GB 2312不能處理,因此微軟利用了GB2312中未使用的編碼空間,收錄了GB13000中的所有字符制定了漢字內碼擴展規範GBK(K爲漢語拼音 Kuo Zhan中“擴”字的首字母)。所以這一關係其實是大陸把Unicode1.1借鑑過來改名爲了GB13000,而微軟則利用GB2312中未使用的編碼空間收錄GB13000制定了GBK。所以GBK是向下完全兼容GB2312的。

包含字符:

共收錄21886個字符, 其中漢字21003個, 字符883個

編碼方式:

GBK只不過是把GB2312中未使用的空間,編碼了其他字符,所以GBK同樣是用兩個字節爲每個字符進行編碼。

GB18030

微軟到了99年前後,說GBK已經落伍了,現在流行UTF-8標準,準備全盤轉換成UTF-8,但中國ZF不是吃素的,編寫並強制推出了GB18030標準。GB18030的誕生還有一個原因是GBK只包含了大部分的漢字和繁體字等,我們的少數民族兄弟根本木有考慮!中國有56個民族,其中有12個民族有自己的文字,那怎麼辦呢?在2000年,電子工業標準化研究所起草了GB18030標準,項目代號“GB 18030-2000”,全稱《信息技術-信息交換用漢字編碼字符集-基本集的擴充》。此標準推出後,在中國大陸之後的所售產品必須強制支持GB18030標準,不然不得賣!(這招挺狠的 - -#)

版本:

  • GB 18030-2000
  • GB 18030-2005

包含字符:

GB18030收錄了GBK中的所有字符,並將Unicode中其他中文字符(少數民族文字、偏僻字)也一併收錄進來重新編碼。其中GB 18030-2000共收錄27533個漢字,而GB 18030-2005共包含70244個漢字。

編碼方式:

採用多字節編碼,每個字符由1或2或4個字節進行編碼

前端眼中的字符編碼

前面我們穿越回過去對字符編碼做了下了解,那麼這些字符編碼跟我們到底有啥關係?

基本原理:

當我們打開編輯器coding時,按下ctrl+s的那一刻,其實等於是將自己的工作成果存儲進了計算機,而這裏最關鍵的是我們以什麼字符編碼來進行存儲,我們以intellij編輯器爲例:

我們在編寫此文檔時,是以UTF-8編碼方式進行coding,當我們按下ctrl+s時,則此文檔以utf-8編碼方式存儲進了計算機(右下角的UTF-8),而head區域中的<meat charset="utf-8">的作用則是告訴瀏覽器此文檔以utf-8編碼方式編碼。 我們此時用Hex編輯器打開這個文件,來看看他的二進制流:

其中紅框標註出的即爲“小海”兩個中文字的二進制流,第一個爲"11100101 10110000 10001111"轉化爲十六進制則爲“E5B08F”,第二個爲“10110101 10110111 00001101”轉化爲十六進制爲“E6B5B7”,而當我們去查詢UTF-8的碼錶時發現“E5B08F”對應的字符爲“小”,“E6B5B7”對應的字符則爲“海”,至此當我們用瀏覽器進行預覽頁面時,由於瀏覽器同樣以UTF-8方式對此頁面進行解碼,“小海”兩個字則可以被正確的顯示出來。

亂碼是個XX

做過前端的基本都遇到過亂碼問題吧?好吧,下面就帶大家來揭開這一神祕的面紗。

我們用notepad打開上面的文件,並重新以GBK方式編碼,然後用intellij打開後:

亂了有木有!居然變成了“C??”,木有道理呀!我在用notepad編輯文件時採用的是gbk編碼,而頭部申明的也是gbk,本身notepad打開也是正常,但用intellij打開卻亂了!

罪魁禍首:編輯器默認編碼。每個編輯器都會有默認編碼,如果沒有爲一個項目單獨設置過默認編碼,打開一個單獨的文件,編輯器往往以自己的默認編碼去解碼這個文件,如上圖,我們的inellij編輯器的默認是UTF-8解碼,而文件是GBK編碼方式,那麼打開肯定就是亂的拉。

所以編輯器也是一個因素,DW則可以智能判斷文件的編碼方式,上述文件用DW打開並不會亂碼,而intellij可能對中文的支持並不是很好,所以還不能智能判斷中文編碼,默認以UTF-8解碼(當然默認編碼自己是可以修改的)。

很多讀者可能還有一個疑問,爲啥亂碼出來的是“C??”? 其實原理已在上面的基本原理中做過介紹,即編輯器ctrl+s存進計算機時是GBK,但嘗試用utf-8來解析,對應的utf-8中的碼錶中卻找到了“C??”,感興趣的同學可以自己研究下。

我們現在將文件重新編輯,即編輯時採用GBK,但頭部申明爲UTF-8:

然後用瀏覽器打開後,就是這樣了:

亂了有木有!這個其實和編輯器打開一個文件亂碼的原理是一致的:即編輯器編碼時所採用的字符編碼和解碼時所採用的字符編碼不一致。上述栗子,我們在coding時採用的是GBK編碼,但頭部卻告訴瀏覽器這個文檔是UTF-8編碼,那麼瀏覽器在用UTF-8解碼時就會出現了亂碼。

 申明編碼的方式

我們在coding時需要告訴瀏覽器自己的文件採用了什麼字符編碼,下面列出一些常見的方法:

<meta charset="gb2312"> //html5
<meta http-equiv="Content-Type" content="text/html; charset=gb2312"> //html4 xhtml
<script src="http://ossweb-img.qq.com/images/js/foot.js" charset="gb2312"></script>
<link href="http://gameweb-img.qq.com/css/common.css" rel="stylesheet" charset="gb2312" >

我們可以在head區域的meta元素中爲整個頁面申明編碼方式,也可以爲單獨的外鏈文件申明編碼方式(link/script等元素)。問題是如果頁面頭部和外鏈文件中只有部分申明或者全部申明,那麼對應的到底是以什麼方式解碼呢?這裏就有一個優先級的問題,具體的判定關係如下:

通過上述判定,我們其實可以發現,一個頁面中優先級最高的其實是服務端的編碼設置,如果一旦服務端設置了編碼A,那麼頁面即以A來解析。 目前Google採用的是這一做法,這樣的傳輸效率會更高,不需要在頭部額外再單獨申明編碼,但這樣其實也有一定的風險,除了需要有一個嚴謹的編碼規範,還需要確保服務器上的頁面都保持同一編碼,一旦不一致就會造成亂碼,所以目前這一方案在國內用的並不多。 其他的,如果外鏈資源設置了編碼C,那麼即以C來解析,無論服務端和頭部是否申明編碼。 但必須要提醒大家的是:申明的編碼只是告訴瀏覽器相關的內容是以什麼方案去解碼,並不是這一部分內容就採用了這個編碼。所以大家在coding時的編碼一定要確保和你申明的保持統一,不然就會出現亂碼的問題。

BOM是個神馬

BOM是byte-order mark的縮寫,爲Unicode標準爲了用來區分一個文件是UTF-8還是UTF-16或UTF-32編碼方式的記號,又稱字節序。

UTF-8以單字節爲編碼單元,並沒有字節序的問題,而UTF-16以兩個字節爲編碼單元,在解釋一個UTF-16文本前,首先要弄清楚每個編碼單元的字節序。例如“奎”的Unicode編碼是594E,“乙”的Unicode編碼是4E59。如果我們收到UTF-16字節流“594E”,那麼這是“奎”還是“乙”?這是UTF-16文件開頭的BOM就有作用了。

採用Unicode編碼方式的文件如果開頭出現了“FEFF”,“FEFF”在UCS中是不存在的字符,也叫做“ZERO WIDTH NO-BREAK SPACE”,那麼就表明這個文件的字節流是Big-Endian(高字節在前)的;如果收到“FFFE”,就表明字節流是Little-Endian(低字節在前)。

在UTF-8文件中放置BOM主要是微軟的習慣,BOM其實是爲UTF-16和UTF-32準備的,微軟在UTF-8使用BOM是因爲這樣可以把UTF-8和ASCII等編碼明確區分開,但這樣的文件在Window以外的其他操作系統裏會帶來問題。

我們以Window下的文本文件爲例:

在保存時可以選擇ANSI、Unicode、Unicode big endian和UTF-8四種編碼方式。

  • 其中ANSI是默認的編碼方式,對於英文文件是ASCII編碼,對於簡體中文文件是GB2312編碼(只針對Windows簡體中文版,如果是繁體中文版會採用Big5碼);
  • Unicode其實是UTF-16 endian big編碼方式,這個把帶有BOM的小端序UTF-16稱作Unicode而又不詳細說明,也是微軟的習慣;
  • 而Unicode big endian則是帶有BOM的大端序編碼方式

目前UTF-16通常用於系統文件的編碼,而UTF-32由於對每個字符都採用四個字節編碼,所以現在互聯網中大部分都採用UTF-8來進行編碼傳輸。

關於未來的展望

概述

(左圖:中國地區ALEXA排名前20的站點所採用的編碼佔比)                  (右圖:騰訊互娛所有業務所採用的編碼佔比)

左圖表明GB2312、GBK與UTF-8編碼三分天下,而右圖顯示騰訊互娛的業務大多數採用了GB2312,零星的採用了其他編碼。總的就是不同的字符編碼方案基本都存在了,而這也與各公司業務的歷史原因也有一定的關係。 當我們在項目的最初期時採用了一種非Unicode編碼方案時,隨着業務的壯大,積累的頁面越來越多,到後期想去改成Unicode編碼方案,就會擔心出錯的問題,所以現在大多數公司都採用了延用初期編碼的方式,如淘寶,騰訊互娛等,以及四大門戶。

擺在眼前的問題

可是,某一天了,我們的網站用戶港澳臺用戶也變多了,我們需要支持繁體怎麼辦?

某一天,我們的業務拓展到東南亞了,我們需要我們的網站也能支持那些國家的語言怎麼辦?

如今,國內大多數公司採用的方案是,爲相應的環境單獨做一套編碼文件,如 http://big5.china.com.cn/ ,又如 http://big5.qidian.com

再比如,哪一天了,我們的網站需要支持少數民族的語言怎麼辦?

難道像某某企業這樣切成圖麼?

嗯,這一切都只是暫時的方案,但人一旦變得懶起來,就不願意去改變一些東西,就比如UTF-8。

擁抱國際化標準

一切就等着我們敞開胸懷去擁抱,而不是沉浸在過去的喜悅中。最終的編碼方案決定權在我們自己手裏,改變,只是時間的問題。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章