電腦字元編碼詳盡講解

來源:互聯網
上載者:User

標籤:blog   http   io   ar   使用   sp   for   strong   on   

from http://www.guokr.com/blog/763017/

http://blog.csdn.net/stilling2006/article/details/4129700

下載一個文檔,一開啟發現是亂碼,不抓狂才怪…… 你們都知道,這都是字元編碼闖的禍。ASCII、ANSI、GB18030、Unicode、UTF-8、UTF-8 with BOM、UTF without BOM、UTF-16、UTF-16LE、UTF-16BE…… 一大坨的誰分得清?聽說UTF-8就是Unicode,但怎麼Windows記事本裡的儲存選項有UTF-8和Unicode兩個選項呀?!究竟各種軟體是怎樣判斷一個檔案是什麼編碼呢?為什麼有時候又判斷錯誤呢?讓我一一道來。

世界上本沒有字元編碼。自從有了電腦,我們有了用0和1記錄文字的需求,於是字元就有了編碼。

== ASCII ==

ASCII編碼錶示的“Hello GuoKr”(十進位):72 101 108 111 32 71 117 111 75 114

ASCII是最基本的編碼,它定義了0~127對應的字元,包括最基本的英文字母、標點符號。它無法表示中文。ASCII編碼的文本,每一個位元組都是0~127,如果某個位元組大於127,那它一定不是ASCII編碼。

== GB* / ANSI ==

為了用電腦記錄並顯示中文,中國人發明了GB系列編碼。GB系列編碼定義了中文漢字、標點的編碼。按照GB系列編碼,在一段文本中,如果一個位元組是0~127,那麼這個位元組的含義同ASCII編碼,否則,這個位元組和下一個位元組共同組成漢字(或是GB編碼定義的其他字元)。因此,GB系列編碼向下相容ASCII,也就是說,如果一段用GB編碼文本裡的所有字元都在ASCII中有定義,那麼這段編碼和ASCII編碼完全一樣。GB編碼早期收錄的漢字不足一萬個,基本滿足日常使用需求,但不包含一些生僻的字,後來在一個個新版本中加進去。最早的GB編碼是GB2312,後來有GBK,最新的是GB18030,加入了一些國內少數民族的文字,一些生僻字被編到4個位元組,每擴充一次都完全保留之前版本的編碼,所以每個新版本都向下相容。

同樣,日文、韓文、世界各國文字都有了它們各自的編碼(如果ASCII不能滿足使用要求的話)。這些編碼都和GB編碼相似,相容ASCII並用兩個位元組表示一個字。所有這些各國文字編碼,微軟統稱為ANSI 。所以即使知道是ANSI,我們還需要知道這是哪國文字才能解碼,因為這些編碼都互相衝突。另外,你無法用一段ANSI 編碼錶示既有漢字、又有韓字的文本。

等等,上面我誤導大家了……其實是微軟誤導大家了,嚴格來說ANSI 不是字元編碼,而是美國一個非營利組織,他們做了很多標準制定工作,包括C語言規範ANSI C,還有各國文字編碼對應的“字碼頁”(code page)。ANSI 規定簡體中文GB編碼的字碼頁是936,所以GB編碼又叫做ANSI code page 936(按ANSI標準的字碼頁936),各國編碼被統稱為ANSI 由來於此——這是個離譜的曆史錯誤,這就像我自己給國內的大學做了個排名,排名的依據是飯堂吃出蟲子的機率,然後國內的大學就被統稱為黃油貓。不過對於這些亂七八糟互相衝突的多國字元編碼,有個統稱還是不錯的(我了個去還要謝謝微軟),下面討論姑且繼續使用ANSI 。

==Unicode / UTF / UCS==

為瞭解決衝突的問題,促進世界和平,我們有了Unicode(聯合碼?)——一種將全世界所有語言所有字元都收錄在一起、讓它們和平共處的編碼……哦,等等,Unicode雖是一種字元編碼,但嚴格來說它和GB18030不能相提並論:它只定義了每一個字元對應一個整數(目前包含了十萬多個字元,其中0~127和ASCII完全一樣),但它沒有定義這個整數如何變成位元組。當你告訴我這段資料是Unicode編碼,啊,不好意思,我還是不知道該怎麼解碼——因為變成位元組流的格式不只一種,它們都叫做“Unicode轉換格式”(Unicode Transformation Format,簡稱為UTF)。

所以這裡面就有了一大堆UTF:UTF-8、UTF-8 with BOM、UTF-8 without BOM、UTF-16、UTF-16LE、UTF-16BE…… 還有很少見的UTF-32、,早期還會聽說過UCS-2、UCS-4…… _(:з」∠)_

等等,為什麼Windows記事本裡有個儲存選項是Unicode?這個稍後說。

先說最常見的UTF-8:它將一個字元編為1-4個位元組,其中一個位元組的字元和ASCII 完全一致,所以它也向下相容ASCII。和ANSI類似,UTF-8第一個位元組決定了之後多少個位元組是一組好基友。多數漢字在UTF-8裡為3個位元組,有一些生僻的漢字會編到4位元組。

我們迎來第一種不相容ASCII的編碼:UTF-16。UTF-16以每2個位元組為一個單元,每個字元由1-2個單元組成,所以每個字元可能是2個位元組或者4個位元組,包括最常見的英文字母都會編成兩個位元組。大部分漢字也是2個位元組,少部分生僻字為4個位元組。UTF-16還有講究,一個單元中的兩個位元組的順序不是唯一的。學過電腦原理的同學知道,電腦中表示一個整數分兩種格式:低位在前高位在後,或者反過來。例如用兩個位元組表示260這個整數,可能是:

低位在前:04 01 (260=4+256*1)

高位在前:01 04 (260=256*1+4)

低位在前的UTF-16叫UTF-16LE,高位在前的叫UTF-16BE。目前絕大部分的電腦系統都使用低位在前的整數格式,所以如果沒有聲明,UTF-16預設是LE。

早期Unicode收編的字還不多時,兩個位元組足夠表示所有字元,所以有一種固定為兩個位元組的UTF,叫UCS-2。UTF-16的兩個位元組部分和UCS-2完全一樣,所以UTF-16向下相容UCS-2。UCS-2同樣分LE和BE。而Windows的記事本還有Windows其它地方所謂的Unicode,當代的Windows裡其實是UTF-16LE,在Windows XP和更早的版本裡是UCS-2LE。微軟(又是微軟)正是混淆Unicode概念的禍首,微軟你這麼討厭你家人知道嗎?

此外,UTF-32和UCS-4固定為4個位元組一個字元,同樣分LE和BE。

還沒完,這麼多字元編碼,軟體開啟時如何知道是哪個編碼?於是不知道誰蹲坑時想出了BOM:在一個文字檔或者一段字元編碼前加上幾個固定的位元組用於識別,這些位元組保證不對應任何一個字元,所以軟體一讀就能驗明正身:

EF BB BF - 我是UTF-8

FF FE - 我是UTF-16LE

FE FF - 我是UTF-16BE

(沒有BOM,直奔主題)-你猜?

不錯,沒BOM只能靠猜了。軟體讀入檔案時可以所有編碼都試一下,看哪個像。另外,BOM只針對Unicode系列編碼,ANSI通通不會有BOM。很顯然,沒有BOM難免偶然猜錯。網上就流傳了一個神奇的段子:開啟Windows記事本,打入“聯通”兩個字,儲存,關閉,再開啟,變成了個黑塊。記事本用ANSI(GB18030)儲存聯通這兩個字,剛好這兩個字的GB18030編碼看起來很像UTF-16,於是就當成UTF-16來開啟……

BOM聽起來很不錯,但實際是個討厭的設計,因為它和很多協議、規範不相容,這是題外話。

於是,UTF-8 with BOM、UTF-16 without BOM 你們就懂了。等等,如果不提BOM,究竟有BOM還是沒有BOM?—— 又是一個十分糾結的問題,Windows裡的軟體一般都預設有BOM,而其它系統都預設沒有BOM——可能是因為Windows常要相容ANSI的原因,特別依賴BOM來防止會錯意。

==誰是正統==

這麼多種編碼,用來寫文章就罷了,開啟個文檔看到亂碼就退出、換個程式或者換個編碼再開啟;但寫程式時可半點鐘馬虎不得,各種程式開發環境對編碼支援都不一樣,如果編碼沒搞好,你寫好的程式可能在別人電腦上就運行不起來了。如果我開發跨平台的代碼,而且要有中文(注釋),哪用什麼編碼好?以下是我所知道各開發環境/編譯器支援常見編碼情況(所有=ANSI、UTF-8 BOM and no BOM、UTF-16LE BOM and no BOM):

  • Visual Studio:所有,儲存預設ANSI 。
  • VC編譯器:所有,除了UTF-8 without BOM(直接當成是ANSI )
  • Windows記事本:所有,儲存預設ANSI,無法儲存無BOM。
  • XCode:只支援 UTF-8 without BOM。
  • GCC:所有
  • vim:所有,儲存預設為系統預設編碼,一般是UTF-8 without BOM。
  • Eclipse:所有,儲存預設不明,Mac下居然是ANSI (我們中出了個叛徒)。

ANSI是無法跨境的,用GB寫的文檔拿去韓國就果斷亂碼了。光是簡體中文系統,ANSI 也是經常被認錯的,Eclipse裡經常(不總是)出現開啟ANSI 檔案是亂碼的情況,這是因為ANSI 沒有很明顯的特徵。XCode和Mac的文字編輯器開啟ANSI 直接是亂碼,因為明確不支援。ANSI 容錯性普遍比較差,一個位元組錯了可能導致後面的字通通掛掉。為了防止Eclipse等發神經,也為免跨國帶來麻煩,更為了你自己的資料安全,請遠離ANSI。

UTF-16不相容ASCII,不相容C語言的字串處理庫函數(因為位元組流裡有\0),除了Windows愛用,其它系統都痛恨它。BOM和很多協議規範衝突,很多軟體都抵制,也是只有Windows常用,而且將其列為正統(作反)。

綜上,跨平台開發請使用UTF-8 without BOM,那是最通用的編碼,是很多軟體系統的預設編碼,你在看的網頁也用它。它特徵明顯,除了VC編譯器和微軟的各種軟體外暫時沒發現哪個軟體會有認錯的情況。它還有經過精心設計的容錯機制,錯一個位元組最多隻會錯一個字元。請手動設定你的開發環境,將預設儲存的編碼設為UTF-8 without BOM,並將其它編碼的檔案轉換過來,亂碼就拜拜啦;記事本等不支援的編輯器,不要讓他們摸你的檔案。至於VC編譯器硬要鬧彆扭就由它去吧 _(:з」∠)_

(經過測試,VS2010能正常開啟UTF-8 without BOM的代碼,但可能編譯不通過,並報奇怪的編譯錯誤)

為什麼程式猿那麼喜歡黑微軟啊?因為微軟那群悶騷的設計師總是和大家不太一樣……

寫在最後:

在這個機器能聽懂人語的年代,我們還要操心字元編碼這麼低級的事,真是不可思議…… 解決方案這麼簡單:幾家大公司坐一圈,說定一種編碼,以後通通用一種編碼。而且這種編碼已經浮出水面、支援成熟:UTF-8。我很讚賞蘋果,他們果斷和ANSI還有一大堆不統一的編碼一刀兩段,所有軟體只支援UTF-8,這才是真正對使用者負責 —— 而微軟到今天還死抱著ANSI不放,在這件小事上就看出他就是如此不捨得過去一點的成就,如此不捨得革自己的命。

電腦字元編碼詳盡講解

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.