早期的計算機只支持英文,所以需要表達的字符數(shù)量很少,為此ANSI制定了ASCII字符表,以一個字節(jié)的低7位表示字符,這樣可以表達128個,當字節(jié)的高位為1時,表示的是擴展ASCII字符,ANSI并沒有為它們指定標準。然而,計算機所要表達的并非只有一種語言,為了使ASCII可以支持其他平臺,IBM又做了一些修改,利用兩個擴展ASCII字符來表達非英文字符,這樣可以表達的擴展字符數(shù)就到達了14位,即16384個字符。這就是ANSI字符標準。 針 對ANSI每個國家(地區(qū))有自己的編碼規(guī)范,對中文而言,最早的規(guī)范是大家所熟知的大陸的GB2312-80,臺灣地區(qū)的BIG5以及香港的 HKSCS,后來GB2312發(fā)展成GBK,GBK是GB2312的超集,向下兼容,也就是說GB2312的字符編碼與GBK相同,只是GBK多了一些字 符定義,現(xiàn)在簡體中文的最新編碼規(guī)范是GB18030,它是GBK的超集,向下兼容,但是據(jù)我所知現(xiàn)在還沒有哪個操作系統(tǒng)直接支持它。 上面說到的ANSI對英文和其他語言字符編碼所需要的字節(jié)數(shù)不等,或一個或兩個,所以被稱之為MBCS(多字節(jié)編碼系統(tǒng)),分辨一個字符占用字節(jié)數(shù)的辦法就是看首位是否為1,如果為1,那么連續(xù)的兩個字節(jié)表述一個字符,否則,是一個ASCII碼。 這種編碼規(guī)范使得各種文字可以在本地化后的計算機系統(tǒng)中正確被處理,但是這里還有個國際化的問題,例如,我們在一個文本文件中同時要顯示不同的語言(如中文和日文)時,改怎么辦? 因為ANSI針對每種語言的編碼沒有區(qū)分,所以GB2312的一個字符值在BIG5中可能就有另一個字符與之對應,故在讀取文本的時候必須要清楚使用什么編碼系統(tǒng),否則就會出現(xiàn)亂碼。而對純文本而言,它的編碼方式只能是一種,所以不同語言是不能同時存在的。 這個時候,UNICODE出現(xiàn)了。 UNICODE 使用兩個字節(jié)對世界上幾乎所有的語言進行編碼(0x0000-0xFFFF),它可以表達的字符數(shù)量為16位,即65536個字符,每種語言的代碼段不 同,兩個字節(jié)所表達的字符是唯一的,所以不同語種可以共存于文本中,然后用系統(tǒng)的UNICODE表進行解碼,就可以顯示出來。 unicode與ASCII是兼容的,如ASCII的0X76的UNICODE編碼就是0X0076。 unicode 的兩個字節(jié)在處理的時候順序是不定的,高位字節(jié)在前的我們稱之為unicode big endian,低位在前的稱之為unicode little endian。之所以有這兩種編碼方式是因為他們對應了intel處理器和Mac處理器的處理方法。對一個字符串,究竟采用什么序列解碼呢?這里有個比較 通用的辦法BOM,就是在文本的頭兩個字節(jié)插入標志0xFEFF,它叫做"ZERO WIDTH NO-BREAK SPACE"的,是不存在的unicode字符,所以不應該出現(xiàn)在傳輸中: FF FE: unicode little endian FE FF: unicode big endian unicode并非沒有問題的,我們都知道,現(xiàn)在的計算機是以字節(jié)為處理單位的,字符串在系統(tǒng)中的表達已經(jīng)漸漸形成了規(guī)范,我們來舉個例子: C 中字符串是以'\0'(0x00)結(jié)尾的,當計算機處理的時候看到0x00的時候就知道字符串完了,如果處理的是ANSI編碼自然沒有問題,可是要命的是 unicode編碼中很多字符的兩個字節(jié)中的一個都是0x00,這樣由c處理就會被認為是字符串結(jié)束標志,造成錯誤。解決這個的辦法已經(jīng)有了,就是用 wchar_t表達一個unicode字符,每次讀取兩個字節(jié),以0x0000表示字符串結(jié)束。 另外一個辦法就是使用偉大的UTF(UCS Transformation Format )對Unicode進行編碼。 UTF是通用字符編碼傳輸格式,根據(jù)最小編碼單位不同分為分UTF-8(一個字節(jié)),UTF-16(兩個字節(jié)),UTF-32(4個字節(jié))等,我們這里介紹UTF8。 UTF-8 UTF-8將unicode碼劃分為三段,每一段采用不同的編碼方法: 0x0000-0x007F 0x0******* 一個字節(jié), 7bit 0x0080-0x07FF 0x110***** 0x10****** 兩個字節(jié),11bit 0x0800-0xFFFF 0x1110**** 0x10****** 0x10****** 三個字節(jié),16位 注意,一個字節(jié)的表達完全與ASCII兼容。 我們現(xiàn)在有這么多的unicode編碼方式,那么怎么判斷一個文本使用的是哪種呢?對windows文本文件txt而言,它利用開頭的幾個字節(jié)來判斷: EF BB BF UTF-8 FE FF UTF-16/UCS-2, little endian FF FE UTF-16/UCS-2, big endian FF FE 00 00 UTF-32/UCS-4, little endian. 00 00 FE FF UTF-32/UCS-4, big-endian. 遺憾的是,ANSI沒有辦法與UNICODE區(qū)分。 最后給大家一個實驗環(huán)境: windows 記事本的保存選項有個編碼方式,使用不同的編碼方式編碼文件就會產(chǎn)生不同的文本代碼,然后你用ultraedit打開這些不同編碼的文本文件,在16進制 模式下查看,就會看到區(qū)別了。不過讓我困惑的是,不論它的Unicode編碼方式是什么,文件代碼居然全部都一樣,開頭全部是FFFE,不知道這是為什 么。如果哪位知道,請跟個貼分享一下 |
|