构造BufferWriter和BufferReader实现高效的对象序列化和反序列化
2011-11-02 12:16
507 查看
在之前的文章讲术了如何设计一个简单的网络缓冲区和缓冲池,在.net网络应用中有一个普遍的问题就是如何把对象写入缓冲和从缓冲中读取数据还原对象.在这里会实现一个Writer和Reader方便地把信息写入缓冲区和从缓冲区读取;先看下Writer和Reader功能.
以上两个对象的方法都是基于BitConverter进行基础类型的处理,即方便又高效;但这样会存在一个问题就是不能处理复杂的对象,对于复杂的对象可以采用规则约束的方式来处理;如果对asp.net的ViewState有了解的同学们应该知道有一个IStateManager接口用于对象自定义ViewState存取用的.其实可以直接采用这种方式来给对象进行处理.首先制定一个接口:
实现以上接口实现一个简单自定义序列化对象功能
把对象写入缓冲区
从缓冲区读取对象
以上只是一个简单的对象,下面是构造一个相对复杂点的
测试1
耗时:976.7241(ms)
测试2
耗时:4119.8927(ms)
以上的实现也只是对之前文章提到的缓冲区使用,并没有用到池.对于如何使用池相信兴趣的同学来说没什么问题,需要的就从池中拿,用完就回收就是了.
BufferWriter
View Codepublic class BufferReader : IDisposable { private IList<Buffer> mBuffers; private int mIndex = 0; private Buffer mCursorBuffer; public BufferReader(Encoding coding, IList<Buffer> buffers) { mBuffers = buffers; Coding = coding; foreach (Buffer item in mBuffers) { item.Reset(); } nextBuffer(); } public BufferReader(Encoding coding, BufferWriter write) { Coding = coding; mBuffers = write.Buffers; foreach (Buffer item in mBuffers) { item.Reset(); } nextBuffer(); } public Encoding Coding { get; set; } private void nextBuffer() { mCursorBuffer = mBuffers[mIndex]; mIndex++; } public ArraySegment<byte> Read(int count) { ArraySegment<byte> result = mCursorBuffer.Read(count); if (result.Count == count) return result; int readcount = 0; byte[] data = new byte[count]; while (true) { Array.Copy(result.Array, result.Offset, data, readcount, result.Count); readcount += result.Count; if (readcount >= count) break; nextBuffer(); result = mCursorBuffer.Read(count - readcount); } return new ArraySegment<byte>(data, 0, count); } private T[] createArray<T>() { T[] result = new T[ReadInt32()]; return result; } public bool ReadBool() { ArraySegment<byte> data = Read(1); bool result = BitConverter.ToBoolean(data.Array, data.Offset); return result; } public bool[] ReadBoolArray() { bool[] result = createArray<bool>(); for (int i = 0; i < result.Length; i++) { result[i] = ReadBool(); } return result; } public char ReadChar() { ArraySegment<byte> data = Read(2); char result = BitConverter.ToChar(data.Array, data.Offset); return result; } public char[] ReadCharArray() { char[] result = createArray<char>(); for (int i = 0; i < result.Length; i++) { result[i] = ReadChar(); } return result; } public double ReadDouble() { ArraySegment<byte> data = Read(8); double result = BitConverter.ToDouble(data.Array, data.Offset); return result; } public double[] ReadDoubleArray() { double[] result = createArray<double>(); for (int i = 0; i < result.Length; i++) { result[i]=ReadDouble(); } return result; } public Int16 ReadInt16() { ArraySegment<byte> data = Read(2); Int16 result = BitConverter.ToInt16(data.Array, data.Offset); return result; } public Int16[] ReadInt16Array() { Int16[] result = createArray<Int16>(); for (int i = 0; i < result.Length; i++) { result[i] = ReadInt16(); } return result; } public Int32 ReadInt32() { ArraySegment<byte> data = Read(4); Int32 result = BitConverter.ToInt32(data.Array, data.Offset); return result; } public Int32[] ReadInt32Array() { Int32[] result = createArray<Int32>(); for (int i = 0; i < result.Length; i++) { result[i] = ReadInt32(); } return result; } public Int64 ReadInt64() { ArraySegment<byte> data = Read(8); Int64 result = BitConverter.ToInt64(data.Array, data.Offset); return result; } public Int64[] ReadInt64Array() { Int64[] result = createArray<Int64>(); for (int i = 0; i < result.Length; i++) { result[i] = ReadInt64(); } return result; } public float ReadFloat() { ArraySegment<byte> data = Read(4); Single result = BitConverter.ToSingle(data.Array, data.Offset); return result; } public float[] ReadFloatArray() { float[] result = createArray<float>(); for (int i = 0; i < result.Length; i++) { result[i] = ReadFloat(); } return result; } public DateTime ReadDateTime() { long date = ReadInt64(); return new DateTime(date); } public DateTime[] ReadDateTimeArray() { DateTime[] result = createArray<DateTime>(); for (int i = 0; i < result.Length; i++) { result[i] = ReadDateTime(); } return result; } public string ReadBlock() { int length = ReadInt32(); if (length > 0) return ReadString(length); return null; } public string[] ReadBlockArray() { string[] result = createArray<string>(); for (int i = 0; i < result.Length; i++) { result[i] = ReadBlock(); } return result; } public T ReadObject<T>() where T : IMessage,new() { T item = new T(); item.Load(this); return item; } public IList<T> ReadObjects<T>() where T : IMessage, new() { List<T> items = new List<T>(); int count = ReadInt32(); for (int i = 0; i < count; i++) { items.Add(ReadObject<T>()); } return items; } public string ReadString(int count) { ArraySegment<byte> data = Read(count); string result = Coding.GetString(data.Array, data.Offset, count); return result; } public void Dispose() { foreach (Buffer item in mBuffers) { item.Dispose(); } mBuffers.Clear(); } }
以上两个对象的方法都是基于BitConverter进行基础类型的处理,即方便又高效;但这样会存在一个问题就是不能处理复杂的对象,对于复杂的对象可以采用规则约束的方式来处理;如果对asp.net的ViewState有了解的同学们应该知道有一个IStateManager接口用于对象自定义ViewState存取用的.其实可以直接采用这种方式来给对象进行处理.首先制定一个接口:
public interface IMessage { void Load(BufferReader reader); void Save(BufferWriter writer); }
实现以上接口实现一个简单自定义序列化对象功能
public class User : IMessage { public User() { Accunts = new List<Account>(); } public string Name { get; set; } public string EMail { get; set; } public string City { get; set; } public DateTime Birthdate { get; set; } public void Load(BufferReader reader) { Name = reader.ReadBlock(); EMail = reader.ReadBlock(); City = reader.ReadBlock(); Birthdate = reader.ReadDateTime(); Accunts = reader.ReadObjects<Account>(); } public void Save(BufferWriter writer) { writer.WriteBlock(Name); writer.WriteBlock(EMail); writer.WriteBlock(City); writer.Write(Birthdate); writer.WriteObjects<Account>(Accunts); } }
把对象写入缓冲区
User user = new User(); user.Name = "henryfan"; user.City = "GuangZhou"; user.EMail = "henryfan@msn.com"; user.Birthdate = DateTime.Now; BufferWriter writer = new BufferWriter(Encoding.UTF8); user.Save(writer);
从缓冲区读取对象
User nuser = new User(); BufferReader reader = new BufferReader(Encoding.UTF8, writer); nuser.Load(reader);
以上只是一个简单的对象,下面是构造一个相对复杂点的
public class User : IMessage { public User() { Accunts = new List<Account>(); } public string Name { get; set; } public string EMail { get; set; } public string City { get; set; } public DateTime Birthdate { get; set; } public void Load(BufferReader reader) { Name = reader.ReadBlock(); EMail = reader.ReadBlock(); City = reader.ReadBlock(); Birthdate = reader.ReadDateTime(); Accunts = reader.ReadObjects<Account>(); } public void Save(BufferWriter writer) { writer.WriteBlock(Name); writer.WriteBlock(EMail); writer.WriteBlock(City); writer.Write(Birthdate); writer.WriteObjects<Account>(Accunts); } public IList<Account> Accunts { get; set; } public class Account:IMessage { public Account() { Items = new List<History>(); } public string ID { get; set; } public double Money { get; set; } public IList<History> Items { get; set; } public void Load(BufferReader reader) { ID = reader.ReadBlock(); Money = reader.ReadDouble(); Items = reader.ReadObjects<History>(); } public void Save(BufferWriter writer) { writer.WriteBlock(ID); writer.Write(Money); writer.WriteObjects<History>(Items); } } public class History:IMessage { public string ID { get; set; } public string Type { get; set; } public double Money { get; set; } public DateTime LastChangeDate { get; set; } public void Load(BufferReader reader) { ID = reader.ReadBlock(); Type = reader.ReadBlock(); Money = reader.ReadDouble(); LastChangeDate = reader.ReadDateTime(); } public void Save(BufferWriter writer) { writer.WriteBlock(ID.ToString()); writer.WriteBlock(Type); writer.Write(Money); writer.Write(LastChangeDate); } } }
简单性能测试
以下在一台I5的电脑上做简单的性能测试,编译Release后执行相关程序测试1
static void test1() { User user = new User(); user.Name = "henryfan"; user.City = "GuangZhou"; user.EMail = "henryfan@msn.com"; user.Birthdate = DateTime.Now; for (int i = 0; i < 500000; i++) { BufferWriter writer = new BufferWriter(Encoding.UTF8); user.Save(writer); User nuser = new User(); BufferReader reader = new BufferReader(Encoding.UTF8, writer); nuser.Load(reader); } }
耗时:976.7241(ms)
测试2
static void test() { User user = new User(); user.Name = "henryfan"; user.City = "GuangZhou"; user.EMail = "henryfan@msn.com"; user.Birthdate = DateTime.Now; user.Accunts.Add(new User.Account { ID = "ac1", Money = 5 }); user.Accunts[0].Items.Add(new User.History { ID = Guid.NewGuid().ToString(), LastChangeDate = DateTime.Now, Money = 50, Type = "BBQ" }); user.Accunts[0].Items.Add(new User.History { ID = Guid.NewGuid().ToString(), LastChangeDate = DateTime.Now, Money = 34, Type = "BBE" }); user.Accunts[0].Items.Add(new User.History { ID = Guid.NewGuid().ToString(), LastChangeDate = DateTime.Now, Money = 44, Type = "DDEQ" }); for (int i = 0; i <500000; i++) { BufferWriter writer = new BufferWriter(Encoding.UTF8); user.Save(writer); User nuser = new User(); BufferReader reader = new BufferReader(Encoding.UTF8, writer); nuser.Load(reader); } }
耗时:4119.8927(ms)
以上的实现也只是对之前文章提到的缓冲区使用,并没有用到池.对于如何使用池相信兴趣的同学来说没什么问题,需要的就从池中拿,用完就回收就是了.
相关文章推荐
- C#实现对象的Xml格式序列化及反序列化
- 通过序列化和反序列化实现对象实例化
- C#实现对象的Xml格式序列化及反序列化
- Java对象的序列化和反序列化及其实现和使用
- 什么是序列化和反序列化,可以用来做什么?如何在OC中实现复杂对象的存储
- java执行序列化和反序列化操作实现对象的clone
- 通过序列化和反序列化实现对象实例化
- Redis+protostuff 实现对象序列化保存,反序列化获取
- C#实现对象的Xml格式序列化及反序列化
- jackson实现简单对象的序列化,反序列化
- c#实现对象的xml格式序列化及反序列化
- C#实现对象的Xml格式序列化及反序列化
- IO流实现对象的序列化和反序列化
- C#实现对象的Xml格式序列化及反序列化
- 实现对象的序列化和反序列化
- C#实现对象的Xml格式序列化及反序列化
- C#实现对象的Xml格式序列化及反序列化
- 9月27 对象序列化和反序列化基本实现流程
- Windows CE /SmartDeviceProject 操作Json数据实现对象序列化和反序列化
- 通过序列化和反序列化泛型数据实体集合来实现持久化数据对象的方法