一、前言
在用C语言编程的时候,如果要通过网络或者串口等接口传输一个结构体,通常会将这个结构体指针强转成char类型的指针,然后以char类型传输,在另外一边将接收到的数据的指针再转成想要的结构体指针即可。在C#里显然是不能用这种方法操作的。如果用C#编程,可以将需要传输的对象序列化,再另外一边再进行反序列化。
二、二进制序列化
将一个数据进行二进制序列化需要用到的类为:BinaryFormatter,需要引用的命名空间为:System.Runtime.Serialization.Formatters.Binary;
二进制序列化方法:void Serialize(Stream serializationStream, object graph);
该方法的作用是将graph序列化到指定的流。为了测试方便,可以使用FileStream对象(因为FileStream继承自Stream)以文件的形式存储在本地。如果序列化的是一个自定义类对象,那么该类需要用[Serializable]标记,否则程序运行时会抛出异常。
测试代码如下:
using System;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
namespace Suzkfly
{
class Program
{
static void Main(string[] args)
{
Person zhangsan = new Person();
BinaryFormatter bf = new BinaryFormatter();
using (FileStream fs = File.Create(@"C:\Users\Suzkfly\Desktop\file_test\1.txt"))
{
bf.Serialize(fs, zhangsan);
}
}
}
[Serializable]
public class Person
{
private int age = 18;
private char gender = '男';
private string name = "张三";
}
}
程序运行完之后在我传入的那个路径下就出现了1.txt,打开里面的内容大部分是乱码,但能看到里面有age,gender,name这些字符串。
三、二进制反序列化
二进制的反序列化就是序列化的逆过程,具体内容就不多说了,直接上测试代码,这次测试使用的1.txt就是上一章生成的,但在代码里我故意使了一些坏:
using System;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
namespace Suzkfly
{
class Program
{
static void Main(string[] args)
{
Person zhangsan = new Person();
BinaryFormatter bf = new BinaryFormatter();
using (FileStream fs = File.OpenRead(@"C:\Users\Suzkfly\Desktop\file_test\1.txt"))
{
zhangsan = (Person)bf.Deserialize(fs);
}
Console.WriteLine("zhangsan.age = {0}", zhangsan.age);
Console.WriteLine("zhangsan.gender = {0}", zhangsan.gender);
Console.WriteLine("zhangsan.name = {0}", zhangsan.name);
Console.ReadKey();
}
}
[Serializable]
public class Person
{
public string name;
public char gender;
public int age;
}
}
反序列化也要在类上标记[Serializable],不然运行时会抛出异常。代码中我“使坏”的地方有2处,第一是将每个字段的访问修饰符由private改成了public,第二是调换了三个字段的顺序,但是程序的运行结果是喜人的:

但是不能改变类名,否则程序运行时会抛出异常。如果改变了字段名,但是位置不改变,如将"age",改成"egg",那么程序可以正常运行,egg的值不会变成age的值。这说明反序列化是用类名和字段名去精确匹配的,不会受字段的访问级别和顺序的影响。
四、不序列化
可以在已经被[Serializable]标记过的类中的字段前,用[NonSerialized]表示这个字段不被序列化(也不能反序列化)。
测试程序:
using System;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
namespace Suzkfly
{
class Program
{
static void Main(string[] args)
{
Person zhangsan = new Person();
BinaryFormatter bf = new BinaryFormatter();
using (FileStream fs = File.OpenRead(@"C:\Users\Suzkfly\Desktop\file_test\1.txt"))
{
zhangsan = (Person)bf.Deserialize(fs);
}
Console.WriteLine("zhangsan.age = {0}", zhangsan.Age);
Console.WriteLine("zhangsan.gender = {0}", zhangsan.Gender);
Console.WriteLine("zhangsan.name = {0}", zhangsan.Name);
Console.ReadKey();
}
}
[Serializable]
public class Person
{
private string name;
private char gender;
[NonSerialized]
private int age = 0;
public string Name
{
get
{
return name;
}
}
public char Gender
{
get
{
return gender;
}
}
public int Age
{
get
{
return age;
}
}
}
}
在该程序中使用的序列化的文件中是有age这个字段的,但是因为运行的程序中age是被[NonSerialized]标记的,因此运行的结果,age的值仍然是0。

浙公网安备 33010602011771号