场景简化:
程序中的数据每隔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 }
测试一切正常,搞定了。
发现有些思路什么的不太好写出来,是自己整理的不够清楚,不够到位?
原文:http://www.cnblogs.com/chenshizhutou/p/6720043.html