1. 首页 > 电脑教程 > .NET中的字符串对象序列化

.NET中的字符串对象序列化

本篇扩充阅读将向读者介绍将字符串对象的序列化,这里面的关键是字符串应该如何编码和解码为二进制数值,从而可以把它们保存到文件流(FileStream)中,或者通过网络流(NetworkStream)将它们远程发送到另一台计算机上。

1 引子

在实际开发中,经常需要将一些字符串写入到文本文件中,或者从文本文件中读入字符串,在.NET应用程序中,通常使用StreamReader或StreamWriter两个类完成这一工作,比如以下代码将fileContent字串写入到FileName文件中:

staticvoidWriteFileUseStreamWriter(StringfileContent,StringFileName){  using(StreamWriterwriter=newStreamWriter(FileName))  {    writer.Write(fileContent);  }}

如果你使用.NET基类库中相关类(比如StreamReader或下面用到的File类)去读取这个文件,你会发现一切如你所愿地正常运转:

WriteFileUseStreamWriter("中国ab","test.txt");Console.WriteLine(File.ReadAllText("test.txt"));//输出:“中国ab”

由于多数情况下我们都工作在中文Windows下,而且往往都是某个.NET程序写,另一个.NET程序读,所以,不少.NET程序员可能都没注意到这其中其实存在着一个字符编码的问题,在特定的场合下,这一问题会给我们带来麻烦。

请看图1:

图 1记事本支持的编码方式

默认情况下,Windows记事本以ANSI编码方式保存文件。如图1所示,如果文本内容为“中国ab”,记事本将其以ASNI方式保存为“test.txt”,则以下代码将“罢工”了(参看图2):

Console.WriteLine(File.ReadAllText("test.txt"));图 2 汉字将显示为乱码

如图 2所示,File.ReadAllText方法打开“test.txt”文件时,会发现英文字符可以正常显示,但中文将显示为乱码。

2 了解字符的编码

我们可以做个试验,使用记事本将“中国ab”这个中英混杂的字符串以不同编码方式保存为多个“.txt”文件,然后直接查看其二进制内容:

图 3 比对字符编码

图 3展示了“中国ab”按四种编码方式(ANSI、UTF8、Unicode、Unicode Big Endian)得到的不同二进制数据。

以英文字符“a”为例,ANSI和UTF8得到的数值都是“61”,但Unicode将它扩充为2个字节16位的二进制(“61 00”和“00 61”),所以我们又将这种编码方式称为UTF-16。

UTF-16又可以细分为2种编码方式:Big Endian方式与Little_Edian方式,这两者的唯一区别在于字节排列顺序刚好相反, Little_Edian方式将“a”编码为“61 00”,而Big Endian方式则编码为“00 61”。

现在看看中文字符,“中国”两个汉字,ANSI编码为“D6 D0 B9 FA”,4个字节,一个汉字占两个字节,而UTF8则编码为“E4 B8 AD E5 9B BD”,6个字节,一个汉字占3个字节!这说明UTF8是一种“变长”的编码,可能使用1~4个字节来表示某个字符。

另外,我们看到UTF8和Unicode编码(不管是Big Endian还是Little Endian)前面都有几个标记字符,这些字符放在文本文件的开头,称为“BOM(Byte Order Mark,字节顺序标记)”指明了文本的编码方式,以下是.NET程序中常见的字符编码方式的BOM值:

编码

BOM值

UTF-8

EF 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

了解了上述基础知识,我们就可以依据BOM值自动检测字符串的编码方式,从而正确从二进制数据流中解码,以下代码检测文本二进制数据是否采用UTF8编码:

//打开文件读取二进制数据byte[]FileContents=File.ReadAllBytes(FilePath);intfilelength=FileContents.Length;//检测BOMif(FileContents[0]==0xef&&FileContents[1]==0xbb &&FileContents[2]==0xbf){//按UTF8解码字符串,注意要排除掉BOM占用的3个字节。Stringcontent=Encoding.UTF8.GetString( FileContents,3,filelength-3);Console.WriteLine(content);}

其他的编码方式都可以“依样画葫芦”。

3 详解.NET基类库中与字符编码相关的类

前述代码中的Encoding类是.NET实现字符编码解码的核心类型。图4展示了它的属性:图 4 Encoding类型 如图4所示,Encoding类型提供了UTF8、Unicode等编码和解码器,调用它的Get系列方法完成编码和解码工作,以下为示例代码:

//编码byte[]bytes=Encoding.UTF8.GetBytes("中国ab");foreach(bytevalueinbytes)Console.Write("{0}",value.ToString("x"));//转化为16进制Console.WriteLine();//解码char[]chars=Encoding.UTF8.GetChars(bytes);foreach(charchinchars)Console.Write("{0}",ch);

声明:希维路由器教程网提供的内容,仅供网友学习交流,如有侵权请与我们联系删除,谢谢。ihuangque@qq.com
本文地址:https://www.ctrlcv.com.cn/diannao/169323124810625.html