从程序员的观点看 汉字国标与Unicode
工作中時(shí)常接觸到一些于編碼相關(guān)的術(shù)語,比如ASCII,Unicode,UTF-8,UTF-16 ,UTF-32,在C++編程中經(jīng)常會(huì)遇到char,wchar_t,std::string,std::wstring,std::cout,std::wcout,CString,TCHAR。這么多的術(shù)語到底有什么樣的關(guān)系呢?本文試圖理清這些概念,以及如何應(yīng)用他們。
ASCII與漢字國(guó)標(biāo)
ASCII (American Standard Code for Information Interchange) 是美國(guó)標(biāo)準(zhǔn)信息交換碼。它是一套基于拉丁字母的編碼系統(tǒng),主要用于顯示英語和西歐語言。ASCII使用單字節(jié)進(jìn)行存儲(chǔ),其中保留了最高位,因此可以存儲(chǔ)128個(gè)字符,因此這種編碼標(biāo)準(zhǔn)定義了33個(gè)控制字符和95個(gè)打印字符(包括空格)。
GB 2312或GB 2312-80是一個(gè)簡(jiǎn)體中文字符集的中國(guó)國(guó)家標(biāo)準(zhǔn),全稱為《信息交換用漢字編碼字符集·基本集》,又稱為GB0。GB2312編碼通行于中國(guó)大陸。中國(guó)大陸幾乎所有的中文系統(tǒng)和國(guó)際化的軟件都支持GB 2312。GB 2312的出現(xiàn),基本滿足了漢字的計(jì)算機(jī)處理需要,它所收錄的漢字已經(jīng)覆蓋中國(guó)大陸99.75%的使用頻率。對(duì)于人名、古漢語等方面出現(xiàn)的罕用字,GB 2312不能處理,因此出現(xiàn)了GBK。
GBK是GB2312的一個(gè)擴(kuò)展,使用了GB2312中未使用的一些代碼點(diǎn)。微軟在Win95中以Codepage936實(shí)現(xiàn)了GBK。后來國(guó)家相關(guān)部門又對(duì)GBK擴(kuò)展形成了GBK1.0,它僅僅是GB 2312到GB 13000之間的過渡方案。
GB 13000,中華人民共和國(guó)國(guó)家標(biāo)準(zhǔn)的國(guó)家標(biāo)準(zhǔn)代碼之一,全稱 GB 13000.1-93《信息技術(shù) 通用多八位編碼字符集(UCS)第一部分:體系結(jié)構(gòu)與基本多文種平面》。此標(biāo)準(zhǔn)等同采用國(guó)際標(biāo)準(zhǔn)化組織 ISO/IEC 10646.1:1993《信息技術(shù) 通用多八位編碼字符集(UCS)第一部分:體系結(jié)構(gòu)與基本多文種平面》。GB 13000的字符集包含20,902個(gè)漢字。
GB 18030,全稱:國(guó)家標(biāo)準(zhǔn)GB 18030-2005《信息技術(shù) 中文編碼字符集》,是中華人民共和國(guó)現(xiàn)時(shí)最新的內(nèi)碼字集,是GB 18030-2000《信息技術(shù) 信息交換用漢字編碼字符集 基本集的擴(kuò)充》的修訂版。與GB 2312-1980完全兼容,與GBK基本兼容,支持GB 13000及Unicode的全部統(tǒng)一漢字,共收錄漢字70244個(gè)。GB 18030主要有以下特點(diǎn):采用多字節(jié)編碼,每個(gè)字可以由1個(gè)、2個(gè)或4個(gè)字節(jié)組成。編碼空間龐大,最多可定義161萬個(gè)字符。支持中國(guó)國(guó)內(nèi)少數(shù)民族的文字,不需要?jiǎng)佑迷熳謪^(qū)。
Unicode 編碼
通用字符集(Universal Character Set,UCS)是由ISO制定的編碼方式,采用4字節(jié)編碼。目前廣泛應(yīng)用的 Unicode 版本對(duì)應(yīng)于 UCS-2,使用2字節(jié)的編碼空間。UCS-2定義了字符和2字節(jié)編碼的映射。這樣理論上一共最多可以表示 216 即 65536個(gè)字符。基本滿足各種語言的使用。實(shí)際上UCS-2尚未填滿這16位的編碼,保留了大量空間作為特殊使用或?qū)頂U(kuò)展。USC-2構(gòu)成基本多文種平面(Basic Multilingual Plane,簡(jiǎn)稱 BMP)。
一個(gè)字符的 UCS編碼(Unicode 編碼)是確定的。但是在實(shí)際傳輸過程中,由于不同系統(tǒng)平臺(tái)的設(shè)計(jì)不一定一致,以及出于節(jié)省空間的目的,對(duì) Unicode 編碼的實(shí)現(xiàn)方式有所不同。存儲(chǔ)UCS定義編碼的方式被稱為Unicode轉(zhuǎn)換格式(Unicode Translation Format,簡(jiǎn)稱為 UTF),UTF把字符的編碼(code point)轉(zhuǎn)化為字節(jié)流,根據(jù)轉(zhuǎn)化方式的不同產(chǎn)生了UTF-8,UTF-16等。
例如,如果一個(gè)僅包含基本7位ASCII字符的 Unicode 文件,如果每個(gè)字符都使用2字節(jié)的原 Unicode 編碼傳輸,其第一字節(jié)的8位始終為0。這就造成了比較大的浪費(fèi)。對(duì)于這種情況,可以使用 UTF-8 編碼,這是一種變長(zhǎng)編碼,它將基本7位ASCII字符仍用7位編碼表示,占用一個(gè)字節(jié)(首位補(bǔ)0)。而遇到與其他 Unicode 字符混合的情況,將按一定算法轉(zhuǎn)換,每個(gè)字符使用1-3個(gè)字節(jié)編碼,并利用首位為0或1進(jìn)行識(shí)別。這樣對(duì)以7位ASCII字符為主的西文文檔就大大節(jié)省了編碼長(zhǎng)度(具體方案參見UTF-8)。
再如,如果直接使用與 Unicode 編碼一致(僅限于 BMP 字符)的 UTF-16 編碼,由于每個(gè)字符占用了兩個(gè)字節(jié),在Macintosh (Mac)機(jī)和PC機(jī)上,對(duì)字節(jié)順序的理解是不一致的。這時(shí)同一字節(jié)流可能會(huì)被解釋為不同內(nèi)容,如某字符為十六進(jìn)制編碼4E59,按兩個(gè)字節(jié)拆分為4E和59,在Mac上讀取時(shí)是從低字節(jié)開始,那么在Mac OS會(huì)認(rèn)為此4E59編碼為594E,找到的字符為「奎」,而在Windows上從高字節(jié)開始讀取,則編碼為 U+4E59 的字符為「乙」。就是說在Windows下以UTF-16編碼保存一個(gè)字符「乙」,在Mac OS里打開會(huì)顯示成「奎」。此類情況說明UTF-16的編碼順序若不加以人為定義就可能發(fā)生混淆,于是在 UTF-16 編碼實(shí)現(xiàn)方式中使用了大尾序(Big-Endian, 簡(jiǎn)寫為UTF-16 BE)、小尾序(Little-Endian, 簡(jiǎn)寫為UTF-16 LE)的概念,以及可附加的BOM(Byte Order Mark)解決方案,目前在PC機(jī)上的Windows系統(tǒng)和Linux系統(tǒng)對(duì)于UTF-16編碼默認(rèn)使用UTF-16 LE。(具體方案參見UTF-16)。
此外 Unicode 的實(shí)現(xiàn)方式還包括 UTF-7、Punycode、CESU-8、SCSU、UTF-32等,這些實(shí)現(xiàn)方式有些僅在一定的國(guó)家和地區(qū)使用,有些則屬于未來的規(guī)劃方式。目前通用的實(shí)現(xiàn)方式是 UTF-16小尾序(BOM)、UTF-16大尾序(BOM)和 UTF-8。
C/C++語言對(duì)Unicode的支持
C語言中的wchar_t可以用來部分提供對(duì)Unicode的支持,但是C語言并未定義wchar_t的大小,因此wchar_t的大小是與編譯器相關(guān)的。在Win32平臺(tái)wchar_t是16位,可以用來存儲(chǔ)UTF-16 code unit;在Unix平臺(tái)wchar_t是32位的用來存儲(chǔ)UTF-32 code unit。Std::out用來輸出char和std::string,std::wcout用來輸出wchar_t和std::wcout 。
因此如下代碼在Windows下可以輸出部分CJK漢字,當(dāng)然此程序需要以UNICODE編譯:
void CtestUnicodeDlgDlg::OnBnClickedOk()
{
// TODO: Add your control notification handler code here
TCHAR tch = 0x4E00;
std::wstring text ;
for( ;tch <= 0x9FC3; ++tch){
text += tch;
}
output.SetWindowTextW(text.c_str());
}
VC編譯器會(huì)根據(jù)是否定義了UNICODE宏來決定把TCHAR翻譯成char或wchar_t,更多與此相關(guān)信息請(qǐng)參閱Windows核心編程第2章,UNICODE
以下代碼則可以輸出GBK漢字:
C++0x標(biāo)準(zhǔn)將添加新的類型:std::char16_t和std::char32_t來支持Unicode,他們可以分別用來存儲(chǔ)UTF-16和UTF-32字符串,此外可以使用’u’和’U’來定義常量字符串。
Std::char16_t utf16[] = u”UTF16”;
Std::char32_t utf32[] = U”UTF32”;
同時(shí)還有typedef std::basic_stringu16string
typedef std::basic_stringu32string
當(dāng)然可以使用一些第三方庫比如:i18n。
Windows對(duì)漢字與Unicode的支持
Windows對(duì)本地編碼的實(shí)現(xiàn)稱為Code Page。比如說Windows以code page 54936實(shí)現(xiàn)了GB18030(code page 936實(shí)現(xiàn)了GBK)。Windows XP原生支持GB18030, 而Windows2000需要安裝GB18030支持包,因此使用Win32API (MultiByteToWideChar和WideCharToMultiByte)可以實(shí)現(xiàn)GB18030和UTF-16之間的轉(zhuǎn)換。
在Windows XP操作系統(tǒng)附帶的記事本中,「另存為」對(duì)話框可以選擇的四種編碼方式除去非 Unicode 編碼的ANSI(對(duì)于英文系統(tǒng)即ASCII編碼,中文系統(tǒng)則為GB18030) 外,其余三種為「Unicode」(對(duì)應(yīng)UTF-16 LE)、「Unicode big endian」(對(duì)應(yīng)UTF-16 BE)和「UTF-8」。
非Unicode程序在其它語言的操作系統(tǒng)上會(huì)出現(xiàn)亂碼,原因就是沒有設(shè)置local,比如英文xp系統(tǒng):
另外可以使用AppLocal同時(shí)以不同的Local運(yùn)行多個(gè)程序,Windows 控制臺(tái)不支持Unicode。
Linux對(duì)漢字與Unicode的支持
Linux 系統(tǒng)通過系統(tǒng)local 提供對(duì)區(qū)域編碼的支持,比如:zh_CN.UTF-8。Local的名字采用以下的形式:language(_territory)(.encoding)(@modifier)。Linux通過一系列的環(huán)境變量提供對(duì)多編碼的支持,如果系統(tǒng)只需要使用一種local只需要設(shè)置環(huán)境變量LANG即可。更多信息請(qǐng)參考這里:http://www.linux.com/archive/feature/53781
參考:
維基百科:http://en.wikipedia.org/wiki/Main_Page
MSDN: http://msdn.microsoft.com/en-us/default.aspx
http://www.linux.com/archive/
Unicode標(biāo)準(zhǔn)化組織:http://unicode.org
C++標(biāo)準(zhǔn)委員會(huì):http://www.open-std.org/jtc1/sc22/wg21/docs/papers/
總結(jié)
以上是生活随笔為你收集整理的从程序员的观点看 汉字国标与Unicode的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: FPGA入门 Xilinx暑期学校学习D
- 下一篇: 《左耳听风-高效学习篇》阅读笔记