首页 > 代码库 > C#序列化链表
C#序列化链表
场景简化:
程序中的数据每隔1s实时获得的,存储到链表里,需要及时保存到文件里去。
之前的方法是把链表对象序列化到文件里去,好处是不需要太多处理,不用管链表中是否有元素(相对于后面的第三种方法而言)。可是这样有个问题,每次都得把整个链表序列化到文件里去,当数据多了之后开销挺大的。直觉上应该是每次只把新增的数据追加到文件里就可以了。
为了简洁起见,把异常处理,局部变量声明等的都去了。每次只贴出修改过的类的代码,MeasuredValue是一个类,存储了采集到的数据。
第一版的代码如下:
1 public static class FileSerializer 2 { 3 //stream是调用者负责关闭的 4 public static void Serialize(FileStream stream, object objectToSerialize) 5 { 6 BinaryFormatter bFormatter = new BinaryFormatter(); 7 bFormatter.Serialize(stream, objectToSerialize); 8 } 9 public static T Deserialize<T>(FileStream stream) 10 { 11 T objectToDeSerialize = default(T); 12 BinaryFormatter bFormatter = new BinaryFormatter(); 13 objectToDeSerialize = (T)bFormatter.Deserialize(stream); 14 return objectToDeSerialize; 15 } 16 } 17 class Serialize 18 { 19 public bool SerializeMeasuredData(List<MeasuredValue> values){ 20 SerializeHelper data = http://www.mamicode.com/new SerializeHelper(values);"VALUES", _values, typeof(List<MeasuredValue>)); 42 } 43 private SerializeHelper(SerializationInfo info, StreamingContext context) 44 { 45 _values = (List<MeasuredValue>)info.GetValue(_values, typeof(List<MeasuredValue>)); 46 } 47 48 }
后来想实现每次只把增加的采集数据序列化到文件里。我不确定思路对不对,所以使用快猛糙的方法先实现了一下。
第二版代码如下:
1 class Serialize 2 { 3 uint _id; 4 public bool SerializeMeasuredData(List<MeasuredValue> values){ 5 SerializeHelper data = http://www.mamicode.com/new SerializeHelper(values, _id);"VALUES"+_id.ToString(), _values[_values.Length-1], typeof(MeasuredValue)); 30 } 31 //反序列化时id却由SerializeHelper来维护,因为不可能通过参数传递过来 32 private SerializeHelper(SerializationInfo info, StreamingContext context) 33 { 34 _id = 0; 35 MeasuredValue mv= null; 36 _values = new List<MeasuredValue>(); 37 try{ 38 while(true){ 39 mv = (MeasuredValue)info.GetValue("VALUES"+id.ToString(), typeof(MeasuredValue)); 40 _values.Add(mv); 41 } 42 } 43 catch(Exception ex){//出现异常说明到文件末尾 44 45 } 46 } 47 }
可是测试时出错了,不能正常序列化出链表。各位可以猜到我的问题出在哪里吗?
调式时发现SerializeHelper(SerializationInfo info, StreamingContext context)这个函数中的info变量里,MemberCount值为1, MemberNames[4]中只有MemberNames[0]不会空,是"VALUES0",这样就惨了,说明 SerializeHelper里反序列化和序列化时是对应的。由于序列化时是只写入了一个MeasuredValue,所以反序列化时,只能获得一个MeasuredValue,所以生成链表的操作不能在这个类里进行。对于SerializationInfo.AddValue(String name, object value, Type, type)时的name这个参数的作用,我很是疑惑,看样子这个name不是全局范围的标识符,在上面的例子中,是仅在代表一个SerializeHelper的字节流中起标识符的作用?
本来感觉挺麻烦的,按照我一贯直来直往的思路,需要把List一部分一部分的序列化,之前就搜过,没啥资料,而且我也不知道该怎么组织关键字去搜。后来我想到,可以把必须使用的id封装到一个类中,把链表拆分成单个的元素,序列化时每次写入新增的元素,而反序列化时,把每个元素还原出来,然后根据元素的属性来组装到各自对应的链表中。
新增了一个类ToSeriaMV,把需要的ListName信息和MeasuredValue封装起来,每次序列化和反序列的对象都是它。
第三版代码如下:
1 class ToSeriaMV { 2 MeasuredValue _value; 3 string _listName; 4 public MeasuredValue Value { 5 get { return _value; } 6 } 7 public String Name 8 { 9 get { return _listName; } 10 } 11 12 public ToSeriaMV(MeasuredValue value, string listName){ 13 _value = http://www.mamicode.com/value;"SerializedMV"; 19 ToSeriaMV _toSerialMV; 20 List<MeasuredValue> _values; 21 22 public SerializeHelper(MeasuredValue value,String listName) 23 { 24 _toSerialMV = new ToSeriaMV(value, listName); 25 } 26 private SerializeHelper(SerializationInfo info, StreamingContext context) 27 { 28 _deSerializedSuccessful = false; 29 30 _toSerialMV = (ToSeriaMV)info.GetValue(_name, typeof(ToSeriaMV)); 31 _deSerializedSuccessful = true; 32 } 33 public void GetObjectData(SerializationInfo info, StreamingContext ctxt) 34 { 35 info.AddValue(_name, _toSerialMV, typeof(ToSeriaMV)); 36 } 37 } 38 class Serialize 39 { 40 public bool SerializeMeasuredData(MeasuredValue value, String listName) 41 SerializeHelper data = http://www.mamicode.com/new SerializeHelper(value, listName ); >
测试一切正常,搞定了。
发现有些思路什么的不太好写出来,是自己整理的不够清楚,不够到位?
C#序列化链表