C#中的 序列化和反序列化
什么是序列化和反序列化?
序列化就是把一个对象保存到一个文件或数据库字段中去,反序列化就是在适当的时候把这个文件再转化成原来的对象使用。
我想最主要的作用有:
1、在进程下次启动时读取上次保存的对象的信息
2、在不同的AppDomain或进程之间传递数据
3、在分布式应用系统中传递数据
序列化概念的提出和实现,可以使我们的应用程序的设置信息保存和读取更加方便。
比如,在一台机器上产生一个实例,初始化完毕,然后可以序列化,通过网络传送到另一台机器,然后反序列化,得到对象实例,之后再执行某些业务逻辑,得到结果,再序列化,返回第一台机器,第一台机器得到对象实例,得到结果。
现在开始序列化的具体操作:
我们创建一个简单的类 Product:
1 [Serializable] //必须要有这个标记才能序列化,否则会产生异常 2 public class Product 3 { 4 public long Id; 5 public string Name; 6 public double Price; 7 8 [NonSerialized] //这个特征表示这个属性不能被序列化,注意对比序列化后输出结果的差异 9 public string Notes; 10 11 //构造函数,用于初始化对象 12 public Product(long id,string name ,double price,string notes) 13 { 14 Id = id; 15 Name = name; 16 Price = price; 17 Notes = notes; 18 } 19 20 //重写的 ToString() 方法,用于输出对象 21 public override string ToString() 22 { 23 return string.Format("ID={0}, Name={1}, Price={2}, Notes={3}", Id, Name, Price, Notes); 24 } 25 }
- 第一种方式:使用 BinaryFormatter 类
然后再Main函数中:
class Program { static void Main(string[] args) { //将对象实例加入到泛型集合中 List<Product> products = new List<Product>(); products.Add(new Product(1, "可口可乐", 12.12, "test1")); products.Add(new Product(2, "百事可乐", 11.11, "test2")); products.Add(new Product(3, "非常可乐", 10.11, "test3")); //输出泛型集合中的值 Console.WriteLine("输出Product类:"); foreach (var item in products) { Console.WriteLine(item); } Console.WriteLine(); Console.WriteLine("-------------华丽的分割线--------------"); Console.WriteLine(); //序列化对象,将对象保存到文件中 IFormatter serializer = new BinaryFormatter(); //创建一个 BinaryFormatter 类 FileStream saveFile = new FileStream("Product2.bin", FileMode.Create, FileAccess.Write); //将流中的信息写入到 文件Product2.bin中 serializer.Serialize(saveFile, products); //调用 serializer 类的 Serialize()方法序列化该对象 saveFile.Close(); //关闭流 //反序列化对象,从文件中读出对象的值 FileStream loadFile = new FileStream("Product1.bin", FileMode.Open, FileAccess.Read); List<Product> savedProduct = serializer.Deserialize(loadFile) as List<Product>; //反序列化 loadFile.Close(); Console.WriteLine("从文件中读出对象(序列化后的值):"); foreach (var item in savedProduct) { Console.WriteLine(item); } } }
结果:
注意: 从结果中可以看出, Notes属性没有显示,因为我们在 Product类中给 Notes属性标明了 NoSerialized 特征,所以不能序列化该属性。
因为已经把对象的值存到文件 Product1.bin 中了,所以现在随时可以从该文件中反序列化对象的值了
你可以到项目文件夹中的 ..\bin\Debug 文件夹中找到生成的文件, Product1.bin 文件,打开后如图所示:
- 第二种方式: 使用 SoapFormatter 类 序列化为 Soap 格式的文件, 从文件中反序列化和第一种方法一样,所以这里不再列出
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 6 // SOAP 序列化 7 Product products = new Product(1, "百事可乐", 12.12, "test1"); 8 SoapFormatter serializer2 = new SoapFormatter(); //创建SoapFormatter类的实例 9 FileStream saveFile2 = new FileStream("Product10.soap", FileMode.Create, FileAccess.Write); 10 serializer2.Serialize(saveFile2, products);//调用Serialize()方法 11 saveFile2.Close(); 12 } 13 }
..\bin\Debug 文件夹查看文件内容得到:
- 第三种方式: 使用 XmlSerializer 类序列化对象(xml格式):
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 6 //将对象实例加入到泛型集合中 7 List<Product> products = new List<Product>(); 8 products.Add(new Product(1, "可口可乐", 12.12, "test1")); 9 products.Add(new Product(2, "百事可乐", 11.11, "test2")); 10 products.Add(new Product(3, "非常可乐", 10.11, "test3")); 11 12 // XML 序列化 13 14 XmlSerializer xmlSerializer = new XmlSerializer(typeof(Product)); //创建 XmlSeializer类 15 FileStream saveFile2 = new FileStream("Product110.xml", FileMode.Create, FileAccess.Write); 16 17 for (int i = 0; i < products.Count; i++) //因为集合中有多个对象,所以要分别序列化 18 { 19 xmlSerializer.Serialize(saveFile2, products[i]); 20 } 21 saveFile2.Close(); 22 } 23 }
..\bin\Debug 文件夹查看 Product110.xml 文件内容得到: