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