C#中几种序列化的比较,此次比较只是比较了 序列化的耗时和序列后文件的大小。
几种序列化分别是:
1. XmlSerializer
2. BinaryFormatter
3. DataContractSerializer
4. DataContractJsonSerializer
5. protobuf-net
前四种为.Net 自带的类库,最后一种为 Google Protocol Buffers
首先,选做一个实体类,做为序列化的对象,加入了一个可序列化的字典,让实体类 稍稍的复杂一点。
Code:
[Serializable] [ProtoContract] public class User { [ProtoMember(1)] public int ID { get; set; } [ProtoMember(2)] public string Name { get; set; } [ProtoMember(3)] public int Age { get; set; } [ProtoMember(4)] public SerializableDictionary<Guid, Guid> Dictionary { get; set; } } [Serializable] public class SerializableDictionary<TKey, TValue> : Dictionary<TKey, TValue>, IXmlSerializable { public void WriteXml(XmlWriter write) // Serializer { var keySerializer = new XmlSerializer(typeof(TKey)); var valueSerializer = new XmlSerializer(typeof(TValue)); foreach (KeyValuePair<TKey, TValue> kv in this) { write.WriteStartElement("SerializableDictionary"); write.WriteStartElement("key"); keySerializer.Serialize(write, kv.Key); write.WriteEndElement(); write.WriteStartElement("value"); valueSerializer.Serialize(write, kv.Value); write.WriteEndElement(); write.WriteEndElement(); } }
public void ReadXml(XmlReader reader) // Deserializer { reader.Read(); var keySerializer = new XmlSerializer(typeof(TKey)); var valueSerializer = new XmlSerializer(typeof(TValue)); while (reader.NodeType != XmlNodeType.EndElement) { reader.ReadStartElement("SerializableDictionary"); reader.ReadStartElement("key"); TKey tk = (TKey)keySerializer.Deserialize(reader); reader.ReadEndElement(); reader.ReadStartElement("value"); TValue vl = (TValue)valueSerializer.Deserialize(reader); reader.ReadEndElement(); reader.ReadEndElement(); this.Add(tk, vl); reader.MoveToContent(); } reader.ReadEndElement(); } public XmlSchema GetSchema() { return null; } }
然后,初始化一个集合,有1000个User对象,每个User对象中的字典,有500对Guid
var list = new List<User>(); var random = new Random(); for (int i = 0; i < 1000; i++) { var id = random.Next(0, 10000); var user = new User { ID = id, Name = "Name" + id, Age = random.Next(1, 100) }; var dic = new SerializableDictionary<Guid, Guid>(); for (int j = 0; j < 500; j++) { dic.Add(Guid.NewGuid(), Guid.NewGuid()); } user.Dictionary = dic; list.Add(user); }
最后,开始序列化,计时用 Stopwatch
1. Xml序列化
Stopwatch sw = new Stopwatch(); //XmlSerializer sw.Start(); var xmlSerializer = new XmlSerializer(typeof(List<User>)); const string xmlfile = "xml.txt"; var fi = new FileInfo(xmlfile); using (var stream = fi.Create()) { xmlSerializer.Serialize(stream, list); } sw.Stop(); fi.Refresh(); Console.WriteLine("XML Time : {0} , Size : {1}K", sw.Elapsed, fi.Length / 1024);
2. 二进制序列化
//BinarySerializer sw.Restart(); var binarySerializer = new BinaryFormatter(); const string binaryfile = "binary.txt"; var binaryfi = new FileInfo(binaryfile); using (var stream = binaryfi.Create()) { binarySerializer.Serialize(stream, list); } sw.Stop(); binaryfi.Refresh(); Console.WriteLine("Binary Time : {0} , Size : {1}K", sw.Elapsed, binaryfi.Length / 1024);
3. DataContractSerializer
//DataContractSerializer sw.Restart(); var dataContractSerializer = new DataContractSerializer(typeof(List<User>)); const string dataContractfile = "dataContract.txt"; var dataContractfi = new FileInfo(dataContractfile); using (var stream = dataContractfi.Create()) { dataContractSerializer.WriteObject(stream, list); } sw.Stop(); fi.Refresh(); Console.WriteLine("DataContrac Time : {0} , Size : {1}K", sw.Elapsed, dataContractfi.Length / 1024);
4. DataContractJsonSerializer
//DataContractJsonSerializer sw.Restart(); var dataContractJsonSerializer = new DataContractJsonSerializer(typeof(List<User>)); const string dataContractJsonfile = "dataContractJson.txt"; var dataContractJsonfi = new FileInfo(dataContractJsonfile); using (var stream = dataContractJsonfi.Create()) { dataContractJsonSerializer.WriteObject(stream, list); } sw.Stop(); fi.Refresh(); Console.WriteLine("DataContractJson Time : {0} , Size : {1}K", sw.Elapsed, dataContractJsonfi.Length / 1024);
5. protobuf-net
sw.Restart(); //protobuf-net const string protobuffile = "buffer.txt"; var pbfi = new FileInfo(protobuffile); using (var stream = pbfi.Create()) { Serializer.Serialize(stream, list); } sw.Stop(); fi.Refresh(); Console.WriteLine("Protobuf-net Time : {0} , Size : {1}K", sw.Elapsed, pbfi.Length / 1024);
我连续,测了N次,只贴上3次的结果吧:
看这个结果,Protobuf-net 无论序列化速度,还是序列化的体积都完胜其他几种。
此测试只是个人无聊而为,如果有不合理的地方,请大家指出来。