前言
众所周知计算机只能识别二进制数字,如1010,1001。我们屏幕所看到的文字,字符都是和二进制转换后的结果。将我们的文字按照某种规则转换二进制存储在计算机上,这一个过程叫字符编码,反之就是解码。目前存在多种字符编码方式,一组二进制数字根据不同的解码方式,会得到不同的结果,有时甚至会得到乱码。这也就是为什么我们打开网页时有时会是乱码,打开一个文本文件有时也是乱码,而换了一种编码就恢复正常了。CLR中的所有字符都是16位Unicode来表示的。CLR中的Encoding就是用于字节和字符之间的转换的。更多字符编码知识请参考,字符集和字符编码(Charset & Encoding)
关于Encoding
CLR中的Encoding是在System.Text命名空间下的,它是一个抽象类(abstract class), 所以不能被直接实例化,它主要有如下的派生类:ASCIIEnding,UnicodeEncoding,UTF32Encoding,UTF7Encoding,UTF8Encoding,你可以根据需要选择一个合适的Encoding来进行编码和解码。你也可以调用Encoding的静态属性ASCII,Unicode,UTF32,UTF7,UTF8,来构造一个Encoding。其中Unicode是表示16位Encoding。调用静态属性和实例化一个子类的效果是一样的,如下代码。
1 Encoding encodingUTF8 = Encoding.UTF8; 2 Encoding encodingUTF8 = new UTF8Encoding(true);
以下是这些类型的一些简单描述:
ASCII编码 将16位字符编码成ASCII码,只能转换值小于Ox0080的16字符,并且被转换成单字节,就是说一个字符对应一个字节。当字符都在ASCII范围(0X00~0X7F)内时,可以用这种编码,它的速度非常快,适合于英美地区的字符。这种编码非常有限,汉字会被转换成乱码。在CLR对应ASCIIEndoing。
UTF-16 每个字符编码成2个字节,它不会对字符产生任何影响,也不会涉及到压缩处理,性能非常好,因为CLR中的字符也是16位的Unicode。在CLR中对应UnicodeEncoding。
UTF-32 使用4个字节编码成一个字符。从内存角度上讲,它并不是一种高效能的编码方案,因为第个字符都是4个字节,特别占内存,所以很少用来做文件和网络流的编码解码。在CLR中对应UTF32Encoding。
UTF-8 值在Ox0080之下的字符压缩成一个字符,也就是ASCII码;值在0X0080---0X07FF之间的字符都转换成2个字符,适合用于欧洲和中东地区。0X0800以上被转换成3个字符,适合于东亚地区的字符。代理项被转换成4个字节。因此,它是一种非常流行的编码,适用于互联网。它在处理0X0800以上的字符效率不好UTF-16。在CLR中对应UTF8Encoding。
UTF-7 这咱编码通常用于旧的系统,那时的系统是用7位值表示。目前已经被Unicode协淘汰。在CLR中对应UTF7Encoding。
从性能角度上来讲,如果你的代码需要在多处调用一个Encoding,微软建议你使用静态成员的方式构造一个Encoding对象,而不是构造实例。它的内部实现是一个单例模式。
public static Encoding UTF8 { get { if (utf8Encoding == null) { utf8Encoding = new UTF8Encoding(true); } return utf8Encoding; } }
如果你知道某种编码的代码页(code page)或名字,那么你可以调用Encoding的静态方法GetEncoding(int codepage),GetEncoding(string name)来构造一个Encoding,比如我们常用的用于显示简体中文的gb2312,它的代码页是936,我们就可以这样定义:
Encoding encodingGB2312=Encoding.GetEncoding("gb2312"); Encoding encodingGB2312=Encoding.GetEncoding(936);
目前有几十种文字代码页,分别对应于不同的国家,不同的语言,它们只是对应Unicode字符集里的相一部分,比如说936,它只是对应于Unicode字符集里简体中文的那一部分,如果你想正确的显示繁体字,那么就要用中文繁体对应的代码页950。具体的代码页有哪些可以参考MSDN或园子里这篇文章,C#文字代码页,文字编码的代码页名称速查表。
下面代码可以返回CLR中所有的Encoding。
foreach (EncodingInfo eInfo in Encoding.GetEncodings()) { Console.WriteLine("Encoding code page is {0}, encoding name is {1}", eInfo.CodePage, eInfo.Name); Console.WriteLine("Encoding dispaly name is {0}", eInfo.DisplayName); }
Encoding对象有一个静态属性Default,它返回的也是一个Encoding对象,至于返回哪个语言的Encoding取决于你电脑里-->控制面板->区域和语言 里面的设置,也就是ANSI。如下图,我电脑里设置是Chinses(Simplified, PRC)也就是简体中文,那么对应的就是gb2312,所以下面代码会打印gb2312。如果你的代码在不止一个国家里使用,那么你最好不要Encoding.Default,这样会造成乱码,你最好用Encoding.UTF8。
Encoding encoding1 = Encoding.Default; Console.WriteLine(encoding1.WebName);
待续。。。
下一节将讲如何使用Encoding,BOM,还有Encoder及Decoder。。。。