这些资料是我学习的时候在网络上寻找到的,发布出来希望对大家有帮助,一起努力前进,嘿嘿......Microsoft C#规范 2.0 版 GFC用户提交

feedsky 抓虾 pageflakes google reader my yahoo bloglines 鲜果 有道 http://wap.feedsky.com/bliplink
显示标签为“字符编码”的博文。显示所有博文
显示标签为“字符编码”的博文。显示所有博文

base64编码

base64

  Base64是网络上最常见的用于传输8Bit字节代码的编码方式之一,大家可以查看RFC2045RFC2049,上面有MIME的详细规范。

  Base64要求把每三个8Bit的字节转换为四个6Bit的字节(3*8 = 4*6 = 24),然后把6Bit再添两位高位0,组成四个8Bit的字节,也就是说,转换后的字符串理论上将要比原来的长1/3

  这样说会不会太抽象了?不怕,我们来看一个例子:

  转换前 aaaaaabb ccccdddd eeffffff

  转换后 00aaaaaa 00bbcccc 00ddddee 00ffffff

  应该很清楚了吧?上面的三个字节是原文,下面的四个字节是转换后的Base64编码,其前两位均为0

  转换后,我们用一个码表来得到我们想要的字符串(也就是最终的Base64编码),这个表是这样的:(摘自RFC2045

  Table 1: The Base64 Alphabet

  Value Encoding Value Encoding Value Encoding Value Encoding

  0 A 17 R 34 i 51 z

  1 B 18 S 35 j 52 0

  2 C 19 T 36 k 53 1

  3 D 20 U 37 l 54 2

  4 E 21 V 38 m 55 3

  5 F 22 W 39 n 56 4

  6 G 23 X 40 o 57 5

  7 H 24 Y 41 p 58 6

  8 I 25 Z 42 q 59 7

  9 J 26 a 43 r 60 8

  10 K 27 b 44 s 61 9

  11 L 28 c 45 t 62 +

  12 M 29 d 46 u 63 /

  13 N 30 e 47 v

  14 O 31 f 48 w (pad) =

  15 P 32 g 49 x

  16 Q 33 h 50 y

  让我们再来看一个实际的例子,加深印象!

  转换前 10101101 10111010 01110110

  转换后 00101011 00011011 00101001 00110110

  十进制 43 27 41 54

  对应码表中的值 r b p 2

  所以上面的24位编码,编码后的Base64值为 rbp2

  解码同理,把 rbq2 的二进制位连接上再重组得到三个8位值,得出原码。

  (解码只是编码的逆过程,在此我就不多说了,另外有关MIMERFC还是有很多的,如果需要详细情况请自行查找。)

  用更接近于编程的思维来说,编码的过程是这样的:

  第一个字符通过右移2位获得第一个目标字符的Base64表位置,根据这个数值取到表上相应的字符,就是第一个目标字符。

  然后将第一个字符左移4位加上第二个字符右移4位,即获得第二个目标字符。

  再将第二个字符左移2位加上第三个字符右移6位,获得第三个目标字符。

  最后取第三个字符的右6位即获得第四个目标字符。

  在以上的每一个步骤之后,再把结果与 0x3F 进行 AND 位操作,就可以得到编码后的字符了。

  可是等等……聪明的你可能会问到,原文的字节数量应该是3的倍数啊,如果这个条件不能满足的话,那该怎么办呢?

  我们的解决办法是这样的:原文的字节不够的地方可以用全0来补足,转换时Base64编码用=号来代替。这就是为什么有些Base64编码会以一个或两个等号结束的原因,但等号最多只有两个。因为:

  余数 = 原文字节数 MOD 3

  所以余数任何情况下都只可能是012这三个数中的一个。如果余数是0的话,就表示原文字节数正好是3的倍数(最理想的情况啦)。如果是1的话,为了让Base64编码是4的倍数,就要补2个等号;同理,如果是2的话,就要补1个等号。

  在线转换:http://md5.mmkey.com/base64/

  一个很方便的转换工具:http://www.skycn.com/soft/47792.html



BASE64编码基于十进制的实现方法


BASE64编码基于十进制的实现方法  
 
 
一、BASE64编码的原理  BASE64编码 的原理很简单,其方法是,将输入数据流每次取6 bit(每bit代表1位二进制),不足6bit的补0,这样,每38位字节将编码为46位字节(3×8 → 4×6);不满4个字节的以“=”填充。其实这4个六位字节 仍然是8位,只不过高两位被设置为0。当一个字节只有6位有效时,它的取值空间为到 26次方减63,也就是说被转换的Base64编码的每一个编码的取值空间为(0~63)。事实上,0~63之间的ASCII码有许多不可见字符,所以应该再做一个映射,映射表(码表)为 



  这样就可以将38位字节,转换为4个可见字符。 也就是说,转换后的字符串要比原来的长1/3,扩张率为3:4。 举例说明:  1、当字符串字符个数为3的倍数时;比如字符串“ABC”,其在计算机内存中的十六进制表示为$41$42$43,十进制表示为“65”“66”“67”;二进制表示为01000001  01000010  01000011   将这三个二进制数依次取6bit,  010000/01  0100/0010  01/000011  就转换成了:  010000  010100  001001  000011  将这四个二进制数转换成十六制数为:$10$14$9$3,十进制数位为162093。对照上面的码表,分别查找出对应的字符为QUJD。也是就说字符串“ABC”经过BASE64编码后得出“QUJD”。  这是最简单的情况,即ASCII码字符数刚好可以被3整除。接着继续讨论余数为2、为1的情况。  2、当余数为2时,比如字符串“ce”,其在内存中十六进制表示为$63$65;十进制表示表示99101;二进制表示为  01100011 01100101 依次取6bit 011000/11 0110/0101  这时,第3个字符不足6位,在后面补零,也就是0101变成010100。转换结果为  011000 110110 010100  这3个二进制数转换成十六制数为$18$36$14;十进制数位为245420。对照码表得出结果“Y2U”。编码后的字符个数不足4位,用“=”填充,最后编码得出“Y2U=”。  3、当余数为1时,比如字符串“{”,其在内存中的十六进制表示为$7B,十进制为123,二进制位表示为  01111011 依次取6bit 011110/11   补0后为 011110/110000  转换结果为011110110000  这两个二进制数转换成十六进制数为$1E$30,十进制数为3048。对照码表得出结果为“ew”,补上“=”,最后编码得出“ew= =”。  解码也很简单,是编码的逆过程,即将每个字符对照码表换算成6bit的二进制数,然后重组起来,按8位进行截取,得出原码。

二、BASE64编码的实现方法  BASE64编码的实现方法很多,但大多基于二进制数的移位、与或操作,不便于理解。为此,本人经过摸索,想出了一种基于十进制下的易于掌握的编码方法。根据上述原理,每3个字节将转换成4个字节,也就是说每一个半字节(12bit)正好转换成2个编码后的字符(2×6bit)。在十六进制下半个字节可用0~F表示。为此,依次取字符串在十六进制表示下的三位,通过整除和取余运算很容易得出编码后的2个字符。  比如字符串ABC,其十六进制在内存中表示$414243,依次取3位,得出结果为$414$243,转换成十进制为1044579。将这两个数分别与64进行整除和取余运算  1044 Div 64=16  1044 Mod 64=20    579 Div 64=9   579 Mod 64=3  得出结果为162093。对照上面的码表,编码结果同样为“QUJD”。  在高级语言中,很容易将字符串的十六进制以字符串形式表达出来,然后通过依次截取3个字符转换成整数,最后进行上述运算得出结果。为此,本人编写了一套BASE64编码在Delphi语言中的实现源码:

//
定义码表constBaseTable:string='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';    

//
编码程序Function StrtoBase64(const test:string):string;vars,s1:string;i,p,len,n,Addnum:integer;begin   result:='';   S := '';   for i := 1 to length(test) do   S := S + IntToHex(Ord(test), 2);   //将字符串的十六进制数以字符串的形式表示出来   case (length(s) mod 3) of   0:addnum:=0;   1:begin     s:=s+'00';     addnum:=2;     end;   2:begin     s:=s+'0';     addnum:=1;     end;   end;  len:=length(s) div 3;  for i:=1 to len do  begin   s1:=midstr(S,i*3-2,3);   p:=strtoint('$'+s1);   n:=p div 64;   result:=result+basetable[n+1];   n:=p mod 64;   result:=result+basetable[n+1];  end;  if addnum=1 then result:=result+'==';  if addnum=2 then result[length(result)]:='=';end;

//
解码程序Function Base64toStr(const test:string):string;vars,s1,m:string;i,len,t:integer;begin  Result:='';  if length(test)=0 then exit;  s:=test;  for i:=0 to 1 do if s[length(s)]='=' then setlength(s,length(s)-1);  len:=length(s) div 2;  for i:=1 to len do  begin    s1:=midstr(s,i*2-1,2);    t:=(Pos(s1[1],BaseTable)-1)*64+(Pos(s1[2],BaseTable)-1);    m:=m+inttohex(t,3)  end;  if length(s) mod 2=1 then  begin   t:=(Pos(s[length(s)],BaseTable)-1)*64;   m:=m+inttohex(t,3);   setlength(m,length(m)-2);  end;  len:=length(m) div 2;  for i:=1 to len do  begin   s:=midstr(m,i*2-1,2);   result:=result+chr(strtoint('$'+s));  end;end;




......

[阅读全文]

Unicode编码规范

Unicode编码规范

Unicode编码规范
      10:33
先从ASCII说起。ASCII是用来表示英文字符的一种编码规范,每个ASCII字符占用1个字节(8bits
     
因此,ASCII编码可以表示的最大字符数是256,其实英文字符并没有那么多,一般只用前128个(最高位为0),其中包括了控制字符、

数字、大小写字母和其他一些符号
     

     
而最高位为1的另128个字符被成为“扩展ASCII”,一般用来存放英文的制表符、部分音标字符等等的一些其他符号
     
这种字符编码规范显然用来处理英文没有什么问题
     
。(实际上也可以用来处理法文、德文等一些其他的西欧字符,但是不能和英文通用),但是面对中文、阿拉伯文之类复杂的文字,255

个字符显然不够用
     
于是,各个国家纷纷制定了自己的文字编码规范,其中中文的文字编码规范叫做“GB2312-80”,它是和ASCII兼容的一种编码规范,其

实就是利用扩展ASCII没有真正标准化这一点,把一个中文字符用两个扩展ASCII字符来表示。

      但是这个方法有问题,最大的问题就是,中文文字没有真正属于自己的编码,因为扩展ASCII码虽然没有真正的标准化,但是PC里的

ASCII码还是有一个事实标准的(存放着英文制表符),所以很多软件利用这些符号来画表格。这样的软件用到中文系统中,这些表格符就会被

误认作中文字,破坏版面。而且,统计中英文混合字符串中的字数,也是比较复杂的,我们必须判断一个ASCII码是否扩展,以及它的下一个

ASCII是否扩展,然后才“猜”那可能是一个中文字
     

     
总之当时处理中文是很痛苦的。而更痛苦的是GB2312是国家标准,台湾当时有一个Big5编码标准,很多编码和GB是相同的,所以……,

嘿嘿。
     
这时候,我们就知道,要真正解决中文问题,不能从扩展ASCII的角度入手,也不能仅靠中国一家来解决。而必须有一个全新的编码系统

,这个系统要可以将中文、英文、法文、德文……等等所有的文字统一起来考虑,为每个文字都分配一个单独的编码,这样才不会有上面那种

现象出现。

      于是,Unicode诞生了。
      Unicode
有两套标准,一套叫UCS-2(Unicode-16),用2个字节为字符编码,另一套叫UCS-4(Unicode-32),用4个字节为字符编码。

      以目前常用的UCS-2为例,它可以表示的字符数为2^16=65535,基本上可以容纳所有的欧美字符和绝大部分的亚洲字符 。
      UTF-8
的问题后面会提到 。
     
Unicode里,所有的字符被一视同仁。汉字不再使用“两个扩展ASCII”,而是使用“1Unicode”,注意,现在的汉字是“一个字符

了,于是,拆字、统计字数这些问题也就自然而然的解决了
     

     
但是,这个世界不是理想的,不可能在一夜之间所有的系统都使用Unicode来处理字符,所以Unicode在诞生之日,就必须考虑一个严峻

的问题:和ASCII字符集之间的不兼容问题。

      我们知道,ASCII字符是单个字节的,比如“A”ASCII65。而Unicode是双字节的,比如“A”Unicode0065,这就造成了一个非

常大的问题:以前处理ASCII的那套机制不能被用来处理Unicode
     

     
另一个更加严重的问题是,C语言使用'\0'作为字符串结尾,而Unicode里恰恰有很多字符都有一个字节为0,这样一来,C语言的字符串

函数将无法正常处理Unicode,除非把世界上所有用C写的程序以及他们所用的函数库全部换掉
     

     
于是,比Unicode更伟大的东东诞生了,之所以说它更伟大是因为它让Unicode不再存在于纸上,而是真实的存在于我们大家的电脑中。

那就是:UTF

      UTF= UCS Transformation Format UCS
转换格式
     
它是将Unicode编码规则和计算机的实际编码对应起来的一个规则。现在流行的UTF2种:UTF-8UTF-16
     
其中UTF-16和上面提到的Unicode本身的编码规范是一致的,这里不多说了。而UTF-8不同,它定义了一种“区间规则”,这种规则可以

ASCII编码保持最大程度的兼容
     

      UTF-8
有点类似于Haffman编码,它将Unicode编码为00000000-0000007F的字符,用单个字节来表示;
      00000080-000007FF
的字符用两个字节表示
      00000800-0000FFFF
的字符用3字节表示
     
因为目前为止Unicode-16规范没有指定FFFF以上的字符,所以UTF-8最多是使用3个字节来表示一个字符。但理论上来说,UTF-8最多需要

6字节表示一个字符。

      UTF-8里,英文字符仍然跟ASCII编码一样,因此原先的函数库可以继续使用。而中文的编码范围是在0080-07FF之间,因此是2个字节

表示(但这两个字节和GB编码的两个字节是不同的),用专门的Unicode处理类可以对UTF编码进行处理。

      下面说说中文的问题。
     
由于历史的原因,在Unicode之前,一共存在过3套中文编码标准。
      GB2312-80
,是中国大陆使用的国家标准,其中一共编码了6763个常用简体汉字。Big5,是台湾使用的编码标准,编码了台湾使用的繁体

汉字,大概有8千多个。HKSCS,是中国香港使用的编码标准,字体也是繁体,但跟Big5有所不同。

      3套编码标准都采用了两个扩展ASCII的方法,因此,几套编码互不兼容,而且编码区间也各有不同
     
因为其不兼容性,在同一个系统中同时显示GBBig5基本上是不可能的。当时的南极星、RichWin等等软件,在自动识别中文编码、自动

显示正确编码方面都做了很多努力
     

     
他们用了怎样的技术我就不得而知了,我知道好像南极星曾经以同屏显示繁简中文为卖点。
     
后来,由于各方面的原因,国际上又制定了针对中文的统一字符集GBKGB18030,其中GBK已经在WindowsLinux等多种操作系统中被实

现。

      GBK兼容GB2312,并增加了大量不常用汉字,还加入了几乎所有的Big5中的繁体汉字。但是GBK中的繁体汉字和Big5中的几乎不兼容。
      GB18030
相当于是GBK的超集,比GBK包含的字符更多。据我所知目前还没有操作系统直接支持GB18030

      谈谈Unicode编码,简要解释UCSUTFBMPBOM等名词
     
这是一篇程序员写给程序员的趣味读物。所谓趣味是指可以比较轻松地了解一些原来不清楚的概念,增进知识,类似于打RPG游戏的升级

 



代码页

  对于字符和 Unicode 数据的位模式的定义,此模式代表特定字母、数字或符号(例如 0x20 代表一个空格,而 0x74 代表字符“t”)。一些数据类型每个字符使用一个字节;每个字节可以具有 256 个不同的位模式中的一个模式。

  在计算机中,字符由不同的位模式(ON OFF)表示。每个字节有 8 位,这 8 位可以有 256 种不同的 ON OFF 组合模式。对于使用 1 个字节存储每个字符的程序,通过给每个位模式指派字符可表示最多 256 个不同的字符。2 个字节有 16 位,这 16 位可以有 65,536 种唯一的 ON OFF 组合模式。使用 2 个字节表示每个字符的程序可表示最多 65,536 个字符。

  单字节代码页是字符定义,这些字符映射到每个字节可能有的 256 种位模式中的每一种。代码页定义大小写字符、数字、符号以及 !@#% 等特殊字符的位模式。每种欧洲语言(如德语和西班牙语)都有各自的单字节代码页。虽然用于表示 A Z 拉丁字母表字符的位模式在所有的代码页中都相同,但用于表示重音字符(如"é""á")的位模式在不同的代码页中却不同。如果在运行不同代码页的计算机间交换数据,必须将所有字符数据由发送计算机的代码页转换为接收计算机的代码页。如果源数据中的扩展字符在接收计算机的代码页中未定义,那么数据将丢失。如果某个数据库为来自许多不同国家的客户端提供服务,则很难为该数据库选择这样一种代码页,使其包括所有客户端计算机所需的全部扩展字符。而且,在代码页间不停地转换需要花费大量的处理时间。

  仅靠单字节字符集存储许多语言所使用的字符也是不够的。例如,一些亚洲语言包含上千个字符,所以每个字符必须使用双字节。双字节字符集正是为这些语言定义的。但是,这些语言都有各自的代码页,在运行不同双字节代码页的计算机之间传输数据也存在困难。

  SQL Server 2000 支持以下代码页。

  代码页 描述

  1258 越南语

  1257 波罗的语

  1256 阿拉伯语

  1255 希伯来语

  1254 土耳其语

  1253 希腊语

  1252 拉丁 1 字符 (ANSI)

  1251 西里尔语

  1250 中欧语言

  950 繁体中文

  949 朝鲜语

  936 简体中文

  932 日语

  874 泰国语

  850 多语种 (MS-DOS Latin1)

  437 MS-DOS 美国英语

  为解决在网络中支持多种代码页时出现的字符转换和解释问题,ISO 标准化组织和称为 Unicode Consortium 的团体定义了 Unicode 标准。Unicode 使用双字节存储每个字符。由于 65,536 个字符足以涵盖世界上所有语言常用的字符,因此 Unicode 标准适用于所有的主要语言。如果网络中的所有计算机和程序都使用 Unicode,则无需进行任何字符转换,每个用户与所有其它用户看到的字符完全相同,并且不会丢失任何字符。

  在运行 Microsoft Windows® 操作系统的计算机上,操作系统和 Windows 应用程序使用的代码页由 Windows 区域设置定义。区域设置是在安装操作系统时选择的。Windows 应用程序使用由 Windows 区域设置定义的代码页来解释数据。Windows 应用程序还支持宽字符数据,即 Unicode 数据。

  SQL Server 2000 支持两类字符数据类型:

  Unicode 数据类型 ncharnvarchar ntext。这些数据类型使用 Unicode 字符表示法。代码页不适用于这些数据类型。

  非 Unicode 字符数据类型 charvarchar text。这些数据类型使用单字节或双字节代码页中定义的字符表示法。

  有关字符数据的存储方式以及代码页、Unicode 和排序次序操作的更多信息,请参见在 http://msdn.microsoft.com MSDN® 页中的 Developing International Software for Windows 95 and Windows NT 4.0

  国际化数据和 Unicode

  当只使用字符数据和代码页时,在一个数据库内很难以多种语言存储数据。很难为数据库找到一种代码页,能够存储所需全部语言特有的字符。对于运行各种代码页的不同客户端所读取和更新的特殊字符,要确保正确地转换也很困难。支持国际化客户端的数据库应始终使用 Unicode 数据,而不应使用非 Unicode 数据类型。

  例如,北美洲客户的数据库必须处理三种主要语言:

  墨西哥使用的西班牙文名称和地址。

  魁北克使用的法文名称和地址。

  加拿大的其余地区和美国使用的英文名称和地址。

  当只使用字符列和代码页时须小心,以确保数据库所安装的代码页能够处理这三种语言的字符。当其中一种语言的字符由运行另一种语言的代码页的客户端读取时,必须更加小心以确保能够正确转换字符。

  随着 Internet 的发展,支持众多运行不同区域设置的客户端计算机变得日益重要。很难选择这样一种代码页,使其包含的字符数据类型能够支持全球范围用户所需的全部字符。

  管理国际化数据库中的字符数据的最简单方法是始终使用 Unicode ncharnvarchar ntext 数据类型,代替对应的非 Unicode 数据类型(charvarchar text)。如果所有使用国际化数据库的应用程序也采用 Unicode 变量而不是非 Unicode 变量,那么在系统中的任何地方都无须进行字符转换。每个客户端与所有其它客户端看见的字符数据都完全相同。

  对于可使用单字节代码页的系统,Unicode 数据需要的存储空间是非 Unicode 字符数据的两倍,但却消除了在代码页间转换扩展字符的必要,因此至少部分弥补了上面的不足。使用双字节代码页的系统没有这个问题。

  SQL Server 2000 将所有的文本化系统目录数据都存储在包含 Unicode 数据类型的列中。数据库对象(如表、视图和存储过程)的名称存储在 Unicode 列中。这样就可以只使用 Unicode 开发应用程序,从而避免了所有的代码页转换问题。

  排序次序

  排序次序指定 SQL Server 解释、排序、比较和显示字符数据所使用的规则。例如,排序次序定义"a"是小于、等于还是大于"b"。排序次序定义排序规则是否区分大小写,例如"m""M"是否相同。另外还定义排序规则是否区分重音,例如"á""ä"是否相同。

  SQL Server 2000 对每种排序规则使用两种排序次序,一种用于 Unicode 数据,另一种用于字符代码页。

  许多 SQL Server 排序规则使用相同的代码页,但是代码页的排序次序不同。这使站点得以选择:

  是否仅根据位模式所表示的数字值来排序字符。二进制排序的速度最快,这是因为 SQL Server 不用做任何调整并可使用快速、简单的排序算法。二进制排序次序始终区分大小写。由于代码页中的位模式可能不按照特定语言的字典规则所定义的序列排列,二进制排序有时并不按照使用该语言的用户所期待的序列对字符进行排序。


代码页是按某种顺序排列的选定字符代码(以码位表示的字符)的列表。定义代码页通常是为了支持共享通用书写系统的特定语言或语言组。Windows 代码页包含 256 个代码数据点,并且是从零开始的。在大多数代码页中,代码数据点 0 127 表示的字符相同。这考虑了连续性和旧式代码。代码数据点 128 255 在不同的代码页之间略有不同。



代码页的编码支持



例如,代码页 1253 提供在希腊语书写系统中所需的字符代码。代码页 1252 为拉丁语书写系统(包括英语、德语和法语)提供字符。代码页 1253 中的后 128 个代码数据点包含希腊语字符,代码页 1252 中的后 128 个代码数据点包含重音字符。因此,不能将希腊语和德语存储在同一个代码流中,除非包含指示所引用的代码页的标识符。

双字节字符集 (DBCS) 方案是为包含 256 个以上的字符的语言(如中文、日语和朝鲜语)开发的。在 DBCS 中,一对代码数据点(双字节)表示一个字符。在处理 DBCS 数据时,DBCS 字符的第一个字节(前导字节)不单独处理。它同紧跟在其后的尾字节一起处理。该方案仍然不允许将两种语言(如日语和中文)组合在同一个数据流中,这是因为根据代码页的不同,一对双字节代码数据点可能表示不同的字符。

.NET Framework 为用代码页编码的字符提供了支持。可以使用 Encoding.GetEncoding Method (Int32) 为指定代码页创建一个目标编码对象。将代码页编号指定为 Int32 参数。下面的代码示例可为代码页 1252 创建 Encodingenc



unicode

目录

Unicode 的编码和实现

Unicode 环境

XML Unicode

输入Unicode

  Unicode统一码万国码单一码)是一种在计算机上使用的字符编码。它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。1990年开始研发,1994年正式公布。随着计算机工作能力的增强,Unicode也在面世以来的十多年里得到普及。

  20066的最新版本的 Unicode 2005331推出的Unicode 4.1.0 。另外,5.0 Beta已于20051212日推出,以供各会员评价。

编辑本段Unicode 的编码和实现

  大概来说,Unicode 编码系统可分为编码方式和实现方式两个层次。

  1.编码方式

  Unicode 的编码方式与 ISO 10646 通用字元集(亦称[通用字符集])Universal Character SetUCS)概念相对应,目前的用于实用的 Unicode 版本对应于 UCS-2,使用16位的编码空间。也就是每个字符占用2字节。这样理论上一共最多可以表示 65,536(216次方) 个字符。基本满足各种语言的使用。实际上目前版本的 Unicode 尚未填充满这16位编码,保留了大量空间作为特殊使用或将来扩展。

  上述16Unicode 字符构成基本多文种平面(Basic Multilingual Plane, 简称 BMP)。最新(但未实际广泛使用)的 Unicode 版本定义了16个辅助平面,两者合起来至少需要占据21位的编码空间,比3字节略少。但事实上辅助平面字符仍然占用4字节编码空间,与 UCS-4 保持一致。未来版本会扩充到 ISO 10646-1 实现级别3,即涵盖 UCS-4 的所有字符。UCS-4 是一个更大的尚未填充完全的31位字符集,加上恒为0的首位,共需占据32位,即4字节。理论上最多能表示 2,147,483,648(231次方)个字符,完全可以涵盖一切语言所用的符号。

  BMP 字符的 Unicode 编码表示为 U+hhhh,其中每个 h 代表一个十六进制数位。与 UCS-2 编码完全相同。对应的4字节 UCS-4 编码后两个字节一致,前两个字节的所有位均为0

  2.实现方式

  Unicode 的实现方式不同于编码方式。一个字符的 Unicode 编码是确定的。但是在实际传输过程中,由于不同系统平台的设计不一定一致,以及出于节省空间的目的,对 Unicode 编码的实现方式有所不同。Unicode 的实现方式称为Unicode转换格式(Unicode Translation Format,简称为 UTF)。

  例如,如果一个仅包含基本7ASCII字符的 Unicode 文件,如果每个字符都使用2字节的原 Unicode 编码传输,其第一字节的8位始终为0。这就造成了比较大的浪费。对于这种情况,可以使用 UTF-8 编码,这是一种变长编码,它将基本7ASCII字符仍用7位编码表示,占用一个字节(首位补0)。而遇到与其他 Unicode 字符混合的情况,将按一定算法转换,每个字符使用1-3个字节编码,并利用首位为01进行识别。这样对以7ASCII字符为主的西文文档就大大节省了编码长度(具体方案参见UTF-8)。类似的,对未来会出现的需要4个字节的辅助平面字符和其他 UCS-4 扩充字符,2字节编码的 UTF-16 也需要通过一定的算法进行转换。

  再如,如果直接使用与 Unicode 编码一致(仅限于 BMP 字符)的 UTF-16 编码,由于每个址都不相同,Macintosh机和PC机上对字节顺序的理解是不一致的。这时同一字节流可能会被解释为不同内容,如编码为 U+594E 的字符“奎”同编码为 U+4E59 的“乙”就可能发生混淆。于是在 UTF-16 编码实现方式中使用了大尾序(big-endian)、小尾序(little-endian)的概念,以及BOMByte Order Mark)解决方案。(具体方案参见UTF-16

  此外 Unicode 的实现方式还包括 UTF-7PunycodeCESU-8SCSUUTF-32等,这些实现方式有些仅在一定的国家和地区使用,有些则属于未来的规划方式。目前通用的实现方式是 UTF-16小尾序(BOM)、UTF-16大尾序(BOM)和 UTF-8。在微软公司Windows XP操作系统附带的记事本中,“另存为”对话框可以选择的四种编码方式除去非 Unicode 编码的 ANSI 外,其余三种“Unicode”、“Unicode big endian”和“UTF-8”即分别对应这三种实现方式。

  目前辅助平面的工作主要集中在第二和第三平面的中日韩统一表意文字中,因此包括GBKGB18030Big5等简体中文、正体中文日文韩语以及越南字喃的各种编码与 Unicode 的协调性被重点关注。考虑到 Unicode 最终要涵盖所有的字符,从某种意义而言,这些编码方式也可视作 Unicode 的出现于其之前的既成事实的实现方式,如同ASCII及其扩展Latin-1一样,后两者的字符在16Unicode 编码空间中的编码第一字节各位全为0,第二字节编码与原编码完全一致。但上述东亚语言编码与 Unicode 编码的对应关系要复杂得多。

编辑本段Unicode 环境

  在非 Unicode 环境下,由于不同国家和地区采用的字符集不一致,很可能出现无法正常显示所有字符的情况。微软公司使用了代码页(Codepage)转换表的技术来过渡性的部分解决这一问题,即通过指定的转换表将非 Unicode 的字符编码转换为同一字符对应的系统内部使用的 Unicode 编码。以在“语言与区域设置”中选择一个代码页作为非 Unicode 编码所采用的默认编码方式,936为简体中文GBK950为正体中文Big5(皆指PC上使用的)。在这种情况下,一些非英语的欧洲语言编写的软件和文档很可能出现乱码。而将代码页设置为相应语言中文处理又会出现问题,这一情况无法避免。从根本上说,完全采用统一编码才是解决之道,但目前上无法做到这一点。

  代码页技术现在广泛为各种平台所采用。UTF-7 的代码页是65000UTF-8 的代码页是65001

编辑本段XML Unicode

  XML及其子集HTML采用UTF-8作为标准字集,理论上我们可以在各种支持XML标准的浏览器上显示任何地区文字的网页,只要电脑本身安装有合适的字体即可。可以利用&#nnn;的格式显示特定的字符。nnn代表该字符的十进制 Unicode 代码。如果采用十六进制代码,在编码之前加上x字符即可。但部分旧版本的浏览器可能无法识别十六进制代码。

  然而部分由于 Unicode 版本发展原因,很多浏览器只能显示 UCS-2 完整字符集也即现在使用的 Unicode 版本中的一个小子集。下表可以检验您的浏览器怎样显示各种各样的 Unicode 代码:

  代码 字符标准名称 (英语) 在浏览器上的显示

  A&#大写拉丁字母"A" A

  &#szlig; 小写拉丁字母"Sharp S" ß

  &#thorn; 小写拉丁字母"Thorn" þ

  Δ大写希腊字母"Delta" Δ

  Й 大写斯拉夫字母"Short I" Й

  ק希伯来字母"Qof" ק

  م阿拉伯字母 "Meem" م

  泰文数字 7

  埃塞俄比亚音节文字"Qha" ቐ

  あ日语平假名 "A"

  ア日语片假名 "A"

  叶简体汉字 ""

  叶 繁体汉字 ""

  韩国音节文字 " Yeob"

编辑本段输入Unicode

  

  除了输入法外,操作系统会提供几种方法输入Unicode。像是Windows 2000之后的Windows系统就提供一个可点击的表。例如在Microsoft Word或者金山WPS之下,按下 Alt 键不放,输入 0 和某个字符的 Unicode 编码(十进制),再松开 Alt 键即可得到该字符,如Alt + 033865会得到Unicode字符“叶”(繁体)。另外按Alt + X 组合键,MS Word 也会将光标前面的字符同其十六进制的四位 Unicode 编码进行互相转换。

  Unicode 编码表反弹

  0000-0FFF 8000-8FFF 10000-10FFF 20000-20FFF 28000-28FFF

  1000-1FFF 9000-9FFF 21000-21FFF 29000-29FFF

  2000-2FFF A000-AFFF 22000-22FFF 2A000-2AFFF

  3000-3FFF B000-BFFF 23000-23FFF

  4000-4FFF C000-CFFF 1D000-1DFFF 24000-24FFF 2F000-2FFFF

  5000-5FFF D000-DFFF 25000-25FFF

  6000-6FFF E000-EFFF 26000-26FFF

  7000-7FFF F000-FFFF 27000-27FFF E0000-E0FFF

  Unicode 目前已经有5.0版本。世界上有一大批计算机、语言学等科学家专门研究Unicode,到了现在Unicode标准已经不单是一个编码标准,还是记录人类语言文字资料的一个巨大的数据库,同时从事人类文化遗产的发掘和保护工作。

  对于中文而言,Unicode 16编码里面已经包含了GB18030里面的所有汉字(27484个字),目前Unicode标准准备把康熙字典的所有汉字放入到Unicode 32bit编码中。

  简单地说,Unicode扩展自ASCII字元集。在严格的ASCII中,每个字元用7位元表示,或者电脑上普遍使用的每字元有8位元宽;而Unicode使用全16位元字元集。这使得Unicode能够表示世界上所有的书写语言中可能用於电脑通讯的字元、象形文字和其他符号。Unicode最初打算作为ASCII的补充,可能的话,最终将代替它。考虑到ASCII是电脑中最具支配地位的标准,所以这的确是一个很高的目标。

  Unicode影响到了电脑工业的每个部分,但也许会对作业系统和程序设计语言的影响最大。从这方面来看,我们已经上路了。Windows NT从底层支持Unicode(不幸的是,Windows 98只是小部分支援Unicode)。先天即被ANSI束缚的C程序设计语言通过对宽字元集的支持来支持Unicode


字符编码和解码


字符编码在一系列数字与人们将文本输入到计算机中时希望看到的字符之间提供映射。例如,在多种字符编码(包括许多西方程序员所熟悉的 ASCII 文本和大多数 Microsoft Windows 西文系统使用的默认编码 Windows 代码页 1252)中,大写字母“A”由十进制数 65(十六进制为 41)表示。

字符编码不是提供图形化表示形式的字体,也不是映射到特殊字符编码的标志符号。例如,Microsoft Word 包含一个具有几万个字符的 Arial 版本 (Arial Unicode MS)

所有 XML 处理器都需要识别 Unicode 字符编码的两种转换:UTF-8 UTF-16

下表显示表示同一个西文字符集的不同平台,以及它们如何使用不同的字节表示同一个字符。

字节

Windows (CP1252)

Macintosh (MacRoman)

140

Œ

å

229

å

Â

231

ç

Á

232

è

Ë

233

é

È

分析器可以读入用 ISO-8859-1Big-5 Shift-JIS 编写的文档,而处理规则将所有字符都视为 Unicode。虽然分析器可以读取文档,但对自动检测字符编码有一些限制。例如,8 ASCII 文本是可接受的 UTF-8,而 UTF-8 不只是 8 ASCII 文本。为了执行可靠的处理,使用 UTF-8 UTF-16 以外的字符编码的 XML 文档必须在 XML 声明中包含一个编码声明。这样,分析器或者可以正确读取字符,或者在无法处理编码时报告错误。

XML 声明用基本 ASCII 文本编写,因此,分析器甚至可以读取编码极为不同的文档的内容。编码声明显著提高了正确解释使用 UTF-8 UTF-16 以外的编码的文档的可能性。



UTF-16 UTF-32 编码器可以使用 Big-Endian 字节顺序(从最高有效字节开始),也可以使用 Little-Endian 字节顺序(从最低有效字节开始)。例如,大写拉丁字母 A (U+0041) 的序列化结果(十六进制)如下所示:

  • UTF-16 Big-Endian 字节顺序:00 41

  • UTF-16 Little-Endian 字节顺序:41 00

  • UTF-32 Big-Endian 字节顺序:00 00 00 41

  • UTF-32 Little-Endian 字节顺序:41 00 00 00

或者,Encoding 提供一个前导码(即一个字节数组),可以将它作为编码过程中所产生的字节序列的前缀。如果前导码中包含字节顺序标记(在 Unicode 中,码位为 U+FEFF),则它会帮助解码器确定字节顺序和转换格式或 UTFUnicode 字节顺序标记的序列化结果(十六进制)如下所示:

  • UTF-8EF BB BF

  • UTF-16 Big-Endian 字节顺序:FE FF

  • UTF-16 Little-Endian 字节顺序:FF FE

  • UTF-32 Big-Endian 字节顺序:00 00 FE FF

  • UTF-32 Little-Endian 字节顺序:FF FE 00 00

通常,使用本机字节顺序存储 Unicode 字符的效率更高。例如,在 Little-Endian 平台(如 Intel 计算机)上最好使用 Little-Endian 字节顺序。

有关字节顺序和字节顺序标记的更多信息,请参见 www.unicode.org 上的“The Unicode Standard”Unicode 标准)部分。



......

[阅读全文]