计算机ucs汉字编码,字符编码基础知识 - Unicode,UCS,GBK,GB2312,UTF-8
字符編碼基礎知識- Unicode,UCS,GBK,GB2312,UTF-8
最近遇到一個Unicode和UTF-8關系比較的問題,之前在處理中文顯示時也遇到過類似的問題,于是花時間學習了一下,在此做個總結歸納,借以加深理解。(本文多數內容均來自互聯網,特此申明。)
一、相關概念
1、UCS/ISO 10646
ISO組織制定的國際標準ISO 10646定義了通用字符集(Universal Character Set, UCS)。UCS是所有其他字符集標準的一個超集,它保證與其他字符集是雙向兼容的。就是說,如果你將任何文本字符串翻譯到UCS格式,然后再翻譯回原編碼,你不會丟失任何信息。
ISO 10646定義了一個31位的字符集。然而,在這巨大的編碼空間中,迄今為止只分配了前65534個碼位(0x0000到0xFFFD)。這個UCS的16位子集稱為基本多語言面(Basic Multilingual Plane, BMP)。將被編碼在16位BMP以外的字符都屬于非常特殊的字符(比如象形文字),且只有專家在歷史和科學領域里才會用到它們。
UCS不僅給每個字符分配一個代碼,而且賦予了一個正式的名字。表示一個UCS或Unicode值的十六進制數,通常在前面加上"U+",就象U+0041代表字符"拉丁大寫字母A"。UCS字符U+0000到U+007F與US-ASCII(ISO
646)是一致的,U+0000到U+00FF與ISO
8859-1(Latin-1)也是一致的。從U+E000到U+F8FF,以及BMP以外的大范圍的編碼是為私用保留的。
2、UCS的編碼格式
UCS-2,用2個byte表示一個字符,即可以表示BMP內的全部字符。
UCS-4,用4個byte表示一個字符(實際上只用了31位,最高位必須為0),可以表示所有UCS字符(0~0x10FFFF)。
UCS-2有2^16=65536個碼位,UCS-4有2^31=2147483648個碼位。
UCS -4根據最高位為0的最高字節分成2^7=128個group。每個group再根據次高字節分為256個plane。每個plane根據第3個字節分為256行(rows),每行包含256個cells。當然同一行的cells只是最后一個字節不同,其余都相同。
group 0的plane 0被稱作基本多語言面(Basic Multilingual Plane),即BMP。或者說UCS-4中,高兩個字節為0的碼位被稱作BMP。
將UCS-4的BMP去掉前面的兩個零字節就得到了UCS-2。在UCS-2的兩個字節前加上兩個零字節,就得到了UCS-4的BMP。而目前的UCS-4規范中還沒有任何字符被分配在BMP之外。
3、Unicode
Unicode協會制定的編碼機制,要將全世界常用文字都函括進去。在1.0中是16位編碼,由U+0000到U+FFFF。在2.0開始拋棄了16位限制,原來的16位作為基本位平面(BMP),另外增加了16個位平面,相當于20位編碼,編碼范圍0到0x10FFFF。
4、UTF(UCS/Unicode
Transformation Format)
1)UTF-8就是以8bit為單元對UCS/Unicode進行編碼。從Unicode到UTF-8編碼方式如下。
Unicode
UTF-8
U-00000000 - U-0000007F:
0xxxxxxx
U-00000080 - U-000007FF:
110xxxxx 10xxxxxx
U-00000800 - U-0000FFFF:
1110xxxx 10xxxxxx 10xxxxxx
U-00010000 - U-001FFFFF:
11110xxx 10xxxxxx 10xxxxxx
10xxxxxx
U-00200000 - U-03FFFFFF:
111110xx 10xxxxxx 10xxxxxx
10xxxxxx 10xxxxxx
U-04000000 - U-7FFFFFFF:
1111110x 10xxxxxx 10xxxxxx
10xxxxxx 10xxxxxx 10xxxxxx
xxx的位置由字符編碼數的二進制表示的位填入,越靠右的x具有越少的特殊意義。只用最短的那個足夠表達一個字符編碼數的多字節串。注意在多字節串中,第一個字節的開頭"1"的數目就是整個串中字節的數目。
例如“漢”字的Unicode編碼是6C49。6C49在0800-FFFF之間,所以肯定要用3字節模板了:1110xxxx
10xxxxxx 10xxxxxx。將6C49寫成二進制是:0110
110001 001001,用這個比特流依次代替模板中的x,得到:111001101011000110001001,即E6 B1
89。
UTF-8有以下一些特點:
與CPU字節順序無關,可以在不同平臺之間交流。
容錯能力高,任何一個字節損壞后,最多只會導致一個編碼碼位損失,不會鏈鎖錯誤(如GB碼錯一個字節就會整行亂碼)。
UCS字符U+0000到U+007F
(ASCII)被編碼為字節0x00到0x7F (ASCII兼容)。這意味著只包含7位ASCII字符的文件在ASCII和UTF-8兩種編碼方式下是一樣的。
所有>U+007F的UCS字符被編碼為一個多個字節的串,每個字節都有標記位集。因此,ASCII字節(0x00-0x7F)不可能作為任何其他字符的一部分。
表示非ASCII字符的多字節串的第一個字節總是在0xC0到0xFD的范圍里,并指出這個字符包含多少個字節。多字節串的其余字節都在0x80到0xBF范圍里。這使得重新同步非常容易,并使編碼無國界,且很少受丟失字節的影響。
可以編入所有可能的2^31個UCS代碼
UTF-8編碼字符理論上可以最多到6個字節長,然而16位BMP字符最多只用到3字節長,正式的Unicode定義字符(U+0000 to U+10FFFF)最多占用4個字節。
Bigendian UCS-4字節串的排列順序是預定的。
字節0xFE和0xFF在UTF-8編碼中從未用到。
2)UTF-16:以16bit為單元對UCS/Unicode進行編碼,對于小于0x10000的UCS碼,UTF-16編碼就等于UCS碼對應的16位無符號整數。對于不小于0x10000的UCS碼,定義了一個算法。不過由于實際使用的UCS2,或者UCS4的BMP必然小于0x10000,所以就目前而言,可以認為UTF-16和UCS-2基本相同。另外,UTF-16是變長碼(2個或4個byte),且以雙字節作為編碼單位所以實際存儲、傳輸時與CPU字序有關,因此java有區分UTF-16BE和UTF-16LE兩種charset。
3)UTF-32:僅使用了Unicode范圍(0到0x10FFFF)的32位編碼,相當于UCS-4的子集。
5、中文國際編碼
字符必須編碼后才能被計算機處理。計算機使用的缺省編碼方式就是計算機的內碼。早期的計算機使用7位的ASCII編碼,為了處理漢字,程序員設計了用于簡體中文的GB2312和用于繁體中文的BIG5。
GB2312(1980年)一共收錄了7445個字符,包括6763個漢字和682個其它符號。漢字區的內碼范圍高字節從B0-F7,低字節從A1-FE,占用的碼位是72*94=6768。其中有5個空位是D7FA-D7FE。GB2312支持的漢字太少。1995年的漢字擴展規范GBK1.0收錄了21886個符號,它分為漢字區和圖形符號區。漢字區包括21003個字符。
從ASCII、GB2312到GBK,這些編碼方法是向下兼容的,即同一個字符在這些方案中總是有相同的編碼,后面的標準支持更多的字符。在這些編碼中,英文和中文可以統一地處理。區分中文編碼的方法是高字節的最高位不為0。按照程序員的稱呼,GB2312、GBK都屬于雙字節字符集(DBCS)。
2000年的GB18030是取代GBK1.0的正式國家標準。該標準收錄了27484個漢字,同時還收錄了藏文、蒙文、維吾爾文等主要的少數民族文字。從漢字字匯上說,GB18030在GB13000.1的20902個漢字的基礎上增加了CJK(中日韓)擴展A的6582個漢字(Unicode碼0x3400
– 0x4db5),一共收錄了27484個漢字。
GB18030的編碼采用單字節、雙字節和4字節方案。其中單字節、雙字節和GBK是完全兼容的。4字節編碼的碼位就是收錄了CJK擴展A的6582個漢字。例如:UCS的0x3400在GB18030中的編碼應該是8139EF30,UCS的0x3401在GB18030中的編碼應該是8139EF31。
GB 18030是中國所有非手持/嵌入式計算機系統的強制實施標準。
二、需要注意的關系
1、Unicode與UCS
ISO與Unicode協會是兩個不同的組織,都試圖設計統一字符集,ISO開發了ISO
10646項目,Unicode協會開發了Unicode項目。在1991年前后,雙方都認識到世界不需要兩個不兼容的字符集。于是它們開始合并雙方的工作成果,并為創立一個單一編碼表而協同工作。從Unicode2.0開始,Unicode項目采用了與ISO
10646-1相同的字庫和字碼。目前兩個項目仍都存在,并獨立地公布各自的標準。Unicode協會現在的最新版本是2005年的Unicode
4.1.0。ISO的最新標準是ISO
10646-3:2003。
總結起來,Unicode與ISO
10646是兩個不同的標準,但定義的內容基本相同(BMP部分完全相同),所以基本可以理解為UCS
= Unicode。
2、字符集與編碼格式
ASCII、GB2312、GBK、UCS、Unicode這些都是字符集。字符集定義了字符編碼表,即規定了整數到字符的對應關系,但并沒有規定與這些整數如何表示、保存、傳輸,這些是由編碼格式規定的。例如“漢”字的UCS/Unicode編碼是6C49,你可以用4個ascii數字來傳輸、保存這個編碼;也可以用utf-8編碼:3個連續的字節E6
B1 89來表示它。關鍵在于通信雙方都要認可。UTF-8、UTF-7、UTF-16都是被廣泛接受的方案。UTF-8的一個特別的好處是它與ISO-8859-1完全兼容。UTF是“UCS/Unicode
Transformation Format”的縮寫。
3、big
endian和little
endian
big endian和little
endian是CPU處理多字節數的不同方式。例如“漢”字的Unicode編碼是6C49。那么寫到文件里時,究竟是將6C寫在前面,還是將49寫在前面?如果將6C寫在前面,就是big
endian。如果將49寫在前面,就是little endian。
我們一般將endian翻譯成“字節序”,將big
endian和little endian稱作“大尾”和“小尾”。
三、問題回答
1、Unicode與UTF什么關系?UTF-8和UTF-16的區別是什么,為什么會有不同的UTF編碼,分別適用于什么場景?
Unicode與UTF的關系不用多說,一個是字符集,一個是編碼方式。
UTF-16我理解更適合程序在內存中表示字符、操作字符,因為每個字符都是2個字節的,便于cpu處理,效率高。
UTF-8更適合作為存儲和網絡傳輸的編碼方式,是由其特點決定的,一是容錯性好;二是每個字符的字節數可以由第一個字節開頭的“1”的個數確定,方便判斷字符的結束;三是UTF-8是以字節為單位編碼的,不存在與cpu相關的字節序的問題;四是UTF-8處理ASCII字符有優勢,只用1個字節,省空間,當然這個優勢在處理中文等多字節字符時是沒有的。
2、使用Windows記事本的“另存為”,可以在GBK、Unicode、Unicode
big endian和UTF-8這幾種編碼方式間相互轉換。同樣是txt文件,Windows是怎樣識別編碼方式的呢?我很早前就發現Unicode、Unicode big endian和UTF-8編碼的txt文件的開頭會多出幾個字節,分別是FF、FE(Unicode),FE、FF(Unicode
big endian),EF、BB、BF(UTF-8)。但這些標記是基于什么標準呢?
UTF -8以字節為編碼單元,沒有字節序的問題。UTF-16以兩個字節為編碼單元,在解釋一個UTF-16文本前,首先要弄清楚每個編碼單元的字節序。例如“奎”的Unicode編碼是594E,“乙”的Unicode編碼是4E59。如果我們收到UTF-16字節流“594E”,那么這是“奎”還是“乙”?
Unicode規范中推薦的標記字節順序的方法是BOM。BOM不是“Bill
Of Material”的BOM表,而是Byte Order Mark。BOM是一個有點小聰明的想法:
在UCS編碼中有一個叫做”ZERO
WIDTH NO-BREAK SPACE”的字符,它的編碼是FEFF。而FFFE在UCS中是不存在的字符,所以不應該出現在實際傳輸中。UCS規范建議我們在傳輸字節流前,先傳輸字符”ZERO
WIDTH NO-BREAK SPACE”。
這樣如果接收者收到FEFF,就表明這個字節流是Big-Endian的;如果收到FFFE,就表明這個字節流是Little-Endian的。因此字符”ZERO
WIDTH NO-BREAK SPACE”又被稱作BOM。
UTF -8不需要BOM來表明字節順序,但可以用BOM來表明編碼方式。字符”ZERO
WIDTH NO-BREAK SPACE”的UTF-8編碼是EF
BB BF(讀者可以用我們前面介紹的編碼方法驗證一下)。所以如果接收者收到以EF BB BF開頭的字節流,就知道這是UTF-8編碼了。
Windows就是使用BOM來標記文本文件的編碼方式的。
總結
以上是生活随笔為你收集整理的计算机ucs汉字编码,字符编码基础知识 - Unicode,UCS,GBK,GB2312,UTF-8的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 全国计算机一级准考证号查询
- 下一篇: 计算机网络技术的概况