C#数据流与数据的加密和解密
1. 数据编码和解码:
- 常见的字符集编码方式:
(1)每个国家都有自己的字符编码方式。
(2)要想正确打开一个文件,必须知道它采用的是哪种编码方式,否则就可能会出现乱码。
(3)常见的字符集编码方式:
①ASCII:
ASCII字符集由128个字符组成,包括大小写字母、数字0~9、标点符号、非打印字符(换行符、制表符等4个)以及控制字符(退格、响铃等)。
②Unicode:
Unicode是国际通用的编码方式,可以表示地球上绝大部分地区的文字。这种编码每个字符都占2个字节,例如一个英文字符占2个字节,一个汉字也是2个字节。
C#中的字符和字符串默认采用的都是Unicode编码。
③UTF-8:
UTF-8是在因特网上使用最广泛的一种编码格式。它是Unicode的一种变长字符编码,用1~4个字节表示一个Unicode字符。例如,每个英文字母都占1个字节,每个汉字都占4个字节。
④GB2312和GB18030:
对于简体中文来说,国家规定的编码标准(国标)有两种,一种是GB2312(1980年公布),另一种是GB18030(2000年公布)
GB2312每个汉字的编码长度都占2个字节,这种编码方式最多支持6千多个汉字的编码;
GB18030编码长度为1~4个字节,可支持两万多个汉字的编码。
2. 利用Encoding类实现编码和解码:
- Encoding类位于System.Text命名空间下
- 该类主要用于对字符集进行编码和解码以及将一种编码格式转换为另一种编码格式。
- Encoding类提供的常用属性和方法:
属性和方法 | 解释 |
---|---|
Default属性 | 获取系统的当前ANSI代码页的编码 |
BodyName属性 | 获取可与邮件正文标记一起使用的编码名称。如果当前Encoding无法使用,则为空字符串 |
HeaderName属性 | 获取可与邮件标题标记一起使用的编码名称。如果当前Encoding无法使用,则为空字符串 |
Unicode属性 | 获取Unicode格式的编码(UTF-16) |
UTF8属性 | 获取Unicode格式的编码(UTF-8) |
ASCII属性 | 获取ASCII字符集的编码 |
Convert方法 | 将字节数组从一种编码转换为另一种编码 |
GetBytes方法 | 将一组字符编码为一个字节序列 |
GetString方法 | 将一个字节序列解码为一个字符串 |
GetEncoding方法 | 返回指定格式的编码 |
- Encoding类的基本用法:
(1)获取所有编码名称及其描述信息
(2)获取指定编码名称及其描述信息
(3)不同编码之间的转换
(4)利用Encoding类实现字符串的编码和解码
举例编码:
- 获取所有编码名称及其描述信息:
(1)使用Encoding类静态的GetEncodings方法可得到一个包含所有编码的EncodingInfo类型的数组。
(2)EncodingInfo类同位于System.Text命名空间下,提供有关编码的基本信息。
foreach ( EncodingInfo ei in Encoding.Ge1+tEncodings( ))
{
Encoding en = ei.GetEncoding( );
Console.WriteLine("编码名称:{0,-18},编码描述:{1}", ei.Name, en.EncodingName);
}
- 获取指定编码名称及其描述信息
(1)Encoding类提供了UTF8、ASCII、Unicode等属性,通过这些属性可以获取某个字符集编码。
(2)也可以利用Encoding类静态的GetEndcoing方法来获取。
Encoding ascii = Encoding.ASCII;
Encoding gb2312 = Encoding.GetEncoding("GB2312");
Encoding gb18030 = Encoding.GetEncoding("GB18030");
(3)得到Encoding对象后,即可利用HeaderName属性获取编码名称,利用EncodingName属性获取编码描述。
string s1 = "GB2312的编码名称为:" + gb2312.HeaderName;
string s2 = "GB2312的编码描述为:" + gb2312.EncodingName;
- 不同编码之间的转换
(1)利用Encoding类的Convert方法可将字节数组从一种编码转换为另一种编码,转换结果为一个byte类型的数组。
public static byte[] Convert(
Encoding srcEncoding, //源编码
Encoding dstEncoding, //目标编码
byte[] bytes //待转换的字节数
)
string s = "abcd";
Encoding unicode = Encoding.Unicode;
Encoding utf8 = Encoding.UTF8;
byte[] b = Encoding.Convert(unicode, utf8, unicode.GetBytes(s));
string s1 = utf8.GetString(b);
3. 加密流 CryptoStream
- CryptoStream类位于System.Security.Cryptography命名空间下
- 该类可按加密流的方式加密或者解密数据,而且只能用于对称加密。
- 实现CryptoStream的任何被加密的对象都可以和实现Stream的任何对象链接起来,因此一个对象的流式处理输出可以馈送到另一个对象的输入,而不需要分别存储中间结果。
- 调用构造函数创建CryptoStream对象时,需用目标数据流、要使用的转换和流的模式初始化CryptoStream类的新实例。加密时为写访问模式,解密时为读访问模式。
- CryptoStream类的构造函数语法如下:
public CryptoStream(
Stream stream, //对其执行加密转换的流
ICryptoTransform transform, //要对流执行的加密转换
CryptoStreamMode mode
//CryptoStreamMode枚举,有Read和Write两种
)
- 使用CryptoStream对象时,一般还要借助其他流进行处理。
(1)比如使用FileStream作为目标数据流
(2)再根据创建的CryptoStream对象生成StreamWriter对象
(3)然后调用WriteLine方法,通过CryptoStream将加密后的数据写入FileStream
(4)写入完成后,关闭创建的对象。
(5)此时在文件中保存的就是加密后的数据。 - 解密时,使用和加密时相同的密钥创建CryptoStream实例,并在创建该实例时将构造函数的mode参数改为读模式,再将StreamWriter替换成StreamReader,即可将解密后的数据读取出来。
举例
FileStream fStream = File.Open(FileName,
FileMode.OpenOrCreate