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 = new SerializeHelper(values);
21             FileSerializer.Serialize(stream, data);
22         }
23         public bool DeSerializeMeasuredData(List<MeasuredValue> values)
24         {
25                 SerializeHelper data = null;
26                 stream = File.Open(_fileName, FileMode.Open, FileAccess.Read);
27                 data = FileSerializer.Deserialize<SerializeHelper>(stream);
28                 values = data;
29         }
30         
31}
32     //33     //想在序列化时,序列化某些指定的List,并添加了别的信息所以加了这个SerializeHelper。
34 class SerializeHelper(){
35         List<MeasuredValue> _values;
36         public SerializeHelper(List<MeasuredValue> values){
37             _values = values;
38         }
39         public void GetObjectData(SerializationInfo info, StreamingContext ctxt)
40         {
41             info.AddValue("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 = new SerializeHelper(values, _id);
 6             _id++;
 7             FileSerializer.Serialize(stream, data);
 8         }
 9         public bool DeSerializeMeasuredData(List<MeasuredValue> values)
10         {
11                 SerializeHelper data = null;
12                 stream = File.Open(_fileName, FileMode.Open, FileAccess.Read);
13                 data = FileSerializer.Deserialize<SerializeHelper>(stream);
14                 values = data;
15         }
16     }
17    18   
19 class SerializeHelper(){
20         List<MeasuredValue> _values;
21         _id;
22         public SerializeHelper(List<MeasuredValue> values, uint id){
23             _values = values;
24             _id = id;
25         }
26         
27         public void GetObjectData(SerializationInfo info, StreamingContext ctxt)
28         {
29             info.AddValue("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 = value;
14             _listName = listName;
15         }
16     }
17 class SerializeHelper(){
18         const string _name = "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 = new SerializeHelper(value, listName );            
42             FileSerializer.Serialize(stream, data);
43         }
44         public bool DeSerializeMeasuredData(List<MeasuredValue> values)
45         {
46                 SerializeHelper data = null;
47                 ToSeriaMV toSerialMv = null;
48                 stream = File.Open(_fileName, FileMode.Open, FileAccess.Read);                
49                 
50                 
51                 while(stream.Position<stream.Length){
52                     data = FileSerializer.Deserialize<SerializeHelper>(stream);
53                     ret = data.GetInfo(out toSerialMv);
54                         if(ret==false)
55                             break;
56                         AddToList(toSerialMv, values);     
57                 }                
58         }
59     }

  测试一切正常,搞定了。

  发现有些思路什么的不太好写出来,是自己整理的不够清楚,不够到位?

posted on 2012-11-12 15:56  生栋  阅读(795)  评论(1编辑  收藏  举报

导航