C#中对象串行化技术的探讨

本文介绍了C#中使用SerializableAttribute进行对象串行化的基础用法,并讨论了其占用空间大的缺点。示例代码展示了如何实现CircleF类的串行化和反串行化。同时,提出了自定义串行化方案的必要性,指出C#编译器的串行化可能会保存过多信息。提出了利用BinaryWriter和BinaryReader设计更高效的串行化方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在C#中,利用SerializableAttribute可以很方便的实现对象的串行化,缺点是占用空间大。本文除了介绍该属性的用法之外,还将介绍一种自定义串行化功能的实现方案。

以下代码展示了SerializableAttribute的基本用法:

  1. using System;
  2. using System.IO;
  3. using System.Runtime.Serialization;
  4. using System.Runtime.Serialization.Formatters.Binary;
  5. namespace UseSerializable
  6. {
  7.     [Serializable]
  8.     class PointF
  9.     {
  10.         public float x;
  11.         public float y;
  12.     }
  13.     [Serializable]
  14.     class CircleF
  15.     {
  16.         public PointF Center = new PointF();
  17.         public float Radius;
  18.     }
  19.     class Program
  20.     {
  21.         static void Main(string[] args)
  22.         {
  23.             CircleF circle = new CircleF();
  24.             circle.Center.x = 1.2F;
  25.             circle.Center.y = 1.8F;
  26.             circle.Radius = 1.0F;
  27.             FileStream fsWriter = File.OpenWrite(@"D:/Sample.dat");
  28.             BinaryFormatter fmt = new BinaryFormatter();
  29.             fmt.Serialize(fsWriter, circle);
  30.             fsWriter.Close();
  31.             FileStream fsReader = File.OpenRead(@"D:/Sample.dat");
  32.             CircleF cif = (CircleF)fmt.Deserialize(fsReader);
  33.             fsReader.Close();
  34.             Console.WriteLine(string.Format("{0}, {1}", cif.Center.x, cif.Center.y));
  35.             Console.WriteLine(cif.Radius);
  36.         }
  37.     }
  38. }

下图是串行化后的文件内容:

从中大致可以看出C#编译器是如何完成对象的串行化输入输出的。

遗憾的是,明显感觉到C#的串行化功能保存了大量的信息,这在很多应用中是难以忍受的。

试想一下,在C/C++中,程序员编制的串行化代码,保存的信息量在极限情况下只有3个float数据,共12字节。

出于以上原因,在C#中有必要设计自己的串行化方案。利用System.IO空间中的BinaryWriter和BinaryReader可以轻松实现。

  1. using System;
  2. using System.Text;
  3. using System.IO;
  4. namespace UseSerializable
  5. {
  6.     interface ISerializable
  7.     {
  8.         void Serialize(Stream output, Encoding encoding);
  9.         void Deserialize(Stream input, Encoding encoding);
  10.     }
  11.     class PointF : ISerializable
  12.     {
  13.         public float x;
  14.         public float y;
  15.         public void Serialize(Stream output, Encoding encoding)
  16.         {
  17.             BinaryWriter bw = new BinaryWriter(output, encoding);
  18.             bw.Write(x);
  19.             bw.Write(y);
  20.         }
  21.         public void Deserialize(Stream input, Encoding encoding)
  22.         {
  23.             BinaryReader br = new BinaryReader(input, encoding);
  24.             x = br.ReadSingle();
  25.             y = br.ReadSingle();
  26.         }
  27.     }
  28.     class CircleF : ISerializable
  29.     {
  30.         public PointF Center = new PointF();
  31.         public float Radius;
  32.         public void Serialize(Stream output, Encoding encoding)
  33.         {
  34.             Center.Serialize(output, encoding);
  35.             BinaryWriter bw = new BinaryWriter(output, encoding);
  36.             bw.Write(Radius);
  37.         }
  38.         public void Deserialize(Stream input, Encoding encoding)
  39.         {
  40.             Center.Deserialize(input, encoding);
  41.             BinaryReader br = new BinaryReader(input, encoding);
  42.             Radius = br.ReadSingle();
  43.         }
  44.     }
  45.     class Program
  46.     {
  47.         static void Main(string[] args)
  48.         {
  49.             CircleF circle = new CircleF();
  50.             circle.Center.x = 1.2F;
  51.             circle.Center.y = 1.8F;
  52.             circle.Radius = 1.0F;
  53.             FileStream fsWriter = File.OpenWrite(@"D:/Sample.dat");
  54.             circle.Serialize(fsWriter, Encoding.Default);
  55.             fsWriter.Close();
  56.             FileStream fsReader = File.OpenRead(@"D:/Sample.dat");
  57.             CircleF cif = new CircleF();
  58.             cif.Deserialize(fsReader, Encoding.Default);
  59.             fsReader.Close();
  60.             Console.WriteLine("{0}, {1}", cif.Center.x, cif.Center.y);
  61.             Console.WriteLine(cif.Radius);
  62.         }
  63.     }
  64. }

串行化后的数据只有12字节,请参考下图:

 

总结:

如果不考虑对象的存储空间,使用编译环境支持的Serializable属性是最快捷的方法;

如果对象数量非常大,几千个甚至几万个以上,可以考虑自定义串行化方案。

 

附VS2005自动生成的类图:

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值