4.4 字符编码
【本节示例参考:\示例代码\C04\Example_Encoding】
ASP.NET中的字符串是Unicode编码类型的,对于汉字和英文的操作是相同的。另外,还可以使用System.Text命名空间中的类来对字符串进行编码和解码。System.Text命名空间中的类如图4.5所示。
图4.5 System.Text命名空间
下面,首先介绍字符串编码的基本知识,然后讨论如何使用System.Text中的各个类实现字符串编码操作。
4.4.1 字符编码概述
计算机是0和1的世界,只能表达数字。那么为了在计算机中表示字符,就必须进行编码,如可以指定用65来代表字符“A”。在计算机发展史上,字符编码的标准经历了多个时代,如图4.6所示。
图4.6 字符编码标准发展轨迹
下面对这几种编码简单介绍如下。
1.ASCII编码
在计算机刚刚诞生时,开发者制定ASCII编码。ASCII码由一个字节中的7位表示,范围是0~127,可以表示128个不同的字符,包括英文字母(如ABC、abc)、数字(如123)、常用符号(如~!@),以及特殊符号(如回车)等。在当时,开发者认为这128个字符就足够满足所有的字符应用了。
2.扩展ASCII编码
但时隔不久,开发者们突然发现,在排版中常用的“制表符”没有出现在这128个字符中,只能对ASCII码进行扩展,使用一个字节的全部8位来表示字符,这称为扩展ASCII码,范围是0~255共256个字符,能表示256个不同的字符。
3.多字节字符集
扩展ASCII码在表达西方语言体系的时候是够用了,但是对于表达东方的方块字时,却出现了问题,这是因为方块字并不是由字母排列组合而成,仅仅定义一百多个字母就试图表达所有的方块字行不通。
为了解决汉字的编码表示,中国利用连续2个扩展ASCII码的扩展区域(即160以后)来表示一个汉字,该编码标准为GB-2312。后来,日文、韩文、阿拉伯文、台湾繁体(BIG-5)等方块语言地区都使用类似的方法扩展了本地字符集的定义,统一称为多字节字符集(MBCS)。
4.Unicode编码
多字节字符集解决了表达方块字的问题,但这是有缺陷的,因为各个国家地区定义的字符集有冲突。例如,使用GB-2312的软件,在BIG-5的环境下就会显示乱码,反之亦然。为了解决这个冲突,出现了Unicode标准字符集。Unicode使用2个字节表示一个字符,共6万多个字符,包括英文字母和方块字。
4.4.2 字符编码类
ASP.NET中的字符采用Unicode编码标准,但是,有时候也需要同其他编码标准的程序进行字符数据交互,如调用使用ASCII编码C++实现的COM组件等。为了在各种编码标准的字符间实现转换,.NET提供了几个字符编码类,如表4.4所示。
表4.4 System.Text空间中的编码/解码相关类
|
类 |
说 明 |
|
ASCIIEncoding |
将Unicode字符与ASCII字符相互转换 |
|
Decoder |
将已编码的字节块转换为Unicode字符 |
|
Encoder |
将字符块转换为已编码的字节块 |
|
Encoding |
将字符于多种编码方式互相转换 |
|
UnicodeEncoding |
表示Unicode字符的UTF-16编码 |
|
UTF7Encoding |
表示Unicode字符的UTF-7编码 |
|
UTF8Encoding |
表示Unicode字符的UTF-8编码 |
由于各个类的使用非常类似,在此只对Encoding类进行介绍,其类属性和方法如图4.7所示。
图4.7 Encoding类
此处的属性介绍如下:
(1)ASCII:获取ASCII(7位)字符集的编码对象。
(2)Unicode:获取Unicode格式的编码对象。
(3)UTF7:获取UTF-7格式的编码对象。
(4)UTF8:获取UTF-8格式的编码对象。
(5)EncodingName:获取编码的可读说明。
常用的方法简介如下:
(1)Covert:将字节数组从一种编码转换为另一种。
(2)GetBytes:将指定的String或字符数组的全部或部分内容编码为字节数组。
(3)GetString:将指定字节数组解码为字符串。
下面通过一个示例来说明其应用,示例将使用Encoding类,显示Unicode字符串“M国”的各种编码形式。
代码4-29 显示编码形式:Default.aspx.cs
1. public void test()
2. {
3. String str = "M国"; //C#默认Unicode编码格式
4.
5. //Unicode编码
6. Encoding uni_str = Encoding.Unicode;
7. //获取Unicode编码
8. byte[] uni_byte = uni_str.GetBytes(str);
9. Page.Response.Write("Unicode:");
10. for (int i = 0; i < uni_byte.Length; i++)
11. {
12. Page.Response.Write(uni_byte[i] + " - ");
13. }
14. //获取Unicode编码格式字符串
15. Page.Response.Write(">"+ uni_str.GetString(uni_byte)+"<br />"); //输出:"M国"
16.
17. //ASCII编码
18. Encoding ascii_str = Encoding.ASCII;
19. //获取ASCII编码
20. byte[] ascii_byte = ascii_str.GetBytes(str);
21. Page.Response.Write("ASCII:");
22. for (int i = 0; i < ascii_byte.Length; i++)
23. {
24. Page.Response.Write( ascii_byte[i]+"-");
25. }
26. //获取ASCII编码格式字符串
27. Page.Response.Write(">"+ ascii_str.GetString(ascii_byte)+"<br />");//输出:"M?"
28. }
第3行,示例首先定义了一个Unicode字符串“M国”,注意.NET默认的编码标准为Unicode。
首先,示例显示“M国”的Unicode编码。第6行声明了一个Unicode编码对象,然后在第8行使用了GetBytes方法得到“M国”的Unicode编码。第10~13输出这个编码,应该如下所示:
Unicode:77-0-253-86
其中,77-0为字符“M”的Unicode编码,而253-86为字符“国”的Unicode编码。可以看出,Unicode使用两个字节表示一个中文或英文字符。
第15行使用GetString方法显示Unicode编码的字符串,输出为“M国”。
然后,示例显示“M国”的Unicode编码。第18行声明了一个ASCII编码对象,然后在第20行使用了GetBytes方法得到“M国”的ASCII编码。第22~25输出这个编码,应该如下所示:
ASCII:77-63
其中,77为字符“M”的ASCII编码,而“63”为字符“国”的ASCII编码。
第27行使用GetString方法显示ASCII编码的字符串,输出为“M?”。很明显,可以看出,ASCII试图使用一个字节表示一个字符。对于英文字符而言,没有任何影响。但是对于中文字符,就会丢失了一定的信息,无法正常显示。示例运行结果如图4.8所示。
承上启下
¢ 学完本章后,读者需要回答:
1.能否使用String对象实现字符串的以下操作。
(1)比较:Compare
(2)判定首位:StartsWith|EndsWith
(3)判定子串:Contains
(4)定位子串:IndexOf|IndexOfAny|LastIndexOf|LastIndexOfAny
(5)格式化:Format
(6)连接:Concat|Join
(7)分裂:Split
(8)插入:Insert
(9)填充:PadLeft|PadRight
(10)删除:Remove|Trim/TrimStart/TrimEnd
(11)复制:Copy|CopyTo
(12)替换:Replace
(13)大小写转换:ToUpper|ToLower
2.为什么称StringBuilder对象为动态字符串?它和String对象有何不同之处?
3.如何使用StringBuilder对象完成字符串的以下操作。
(1)设置字符串最大长度:Capacity
(2)追加字符串:Append|AppendFormat
(3)插入字符串:Insert
(4)删除字符串:Remove
(5)替换字符串:Replace
4.什么是正则表达式?是否能够构造匹配URL字符串的正则表达式?
5.如何使用Regex类操作正则表达式?
6.历史上曾经有哪些字符编码标准?.NET中如何实现编码的转换?
¢ 在下一章中,读者将会了解:
1.数组的概念。
2.使用数组完成以下操作。
(1)元素访问:GetValue
(2)转化类型:ConvertAll
(3)遍历数组:foreach
(4)排序数组:Sort
(5)查找元素:BinarySearch/Contains
(6)反转数组:Reverse
(7)复制数组:Copy/CopyTo
3.C#中的集合命名空间包含的常用类,如ArrayList、Queue、Stack等。
4.使用ArrayList类完成以下操作。
(1)添加元素:Add/AddRange
(2)插入元素:Insert/InsertRange
(3)删除元素:Remove/RemoveAt/RemoveRange
(4)排序元素:Sort
(5)查找元素:BinarySeach
5.利用Queue类和Stack类来实现队列及堆栈的以下操作。
(1)入队:Enqueue
(2)出队:Dequeue
(3)入栈:Push
(4)出栈:Pop






