C# 持续序列化对象追加到文件的方法
最近有个需求,将内存和帧数数据序列化到二进制文件。为了节省内存,采用了100个对象的数组,每次存满就序列化到文件,然后归零继续存,以追加的性式继续序列化到原有文件。
这样相当于多个数组对象存在了同一个序列化文件。反序列化的时候需要处理一下。思路是先反序列化出来一个,然后修改文件读取的Offset,继续反序列化下一个,直到文件末尾。
1 namespace ProfilterDataNS 2 { 3 [Serializable] 4 public class ProfilterData 5 { 6 public float fps=0; 7 public float memory=0; 8 } 9 }
1 using System.Collections; 2 using System.Collections.Generic; 3 using ProfilterDataNS; 4 using System.IO; 5 using System.Runtime.Serialization.Formatters.Binary; 6 7 public class DataCache{ 8 string _filePath="profilterData.bin"; 9 int _limitNum=100; 10 int _index=0; 11 ProfilterData [] _cacheArr; 12 FileStream fStream; 13 14 private BinaryFormatter binFormat = new BinaryFormatter();//创建二进制序列化器 15 16 public DataCache(int limitNum,string filePath) 17 { 18 _index=0; 19 _filePath=filePath; 20 _limitNum=limitNum; 21 _cacheArr=new ProfilterData[limitNum]; 22 for(int i=0;i<_cacheArr.Length;i++) 23 { 24 _cacheArr[i]=new ProfilterData(); 25 } 26 //如果有同名旧文件存在,先覆盖一次旧文件 27 fStream = new FileStream(_filePath,FileMode.Create); 28 fStream.Close(); 29 fStream.Dispose(); 30 //以追加的形式 31 fStream=new FileStream(_filePath,FileMode.Append,FileAccess.Write); 32 } 33 34 ~DataCache() 35 { 36 fStream.Close(); 37 fStream.Dispose(); 38 } 39 /// <summary> 40 /// 添加数据 41 /// </summary> 42 /// <param name="fps"></param> 43 /// <param name="memory"></param> 44 public void Append(float fps,float memory) 45 { 46 47 if(_index==_limitNum) 48 { 49 WriteData(_cacheArr); 50 } 51 52 ProfilterData profData=_cacheArr[_index]; 53 profData.fps=fps; 54 profData.memory=memory; 55 _index++; 56 } 57 58 59 /// <summary> 60 /// 立即结算数据,通常在结束时调用 61 /// </summary> 62 public void SettleAtOnce() 63 { 64 if(_index!=0) 65 { 66 ProfilterData [] tempArr=new ProfilterData[_index]; 67 for(int i=0;i<tempArr.Length;i++) 68 { 69 tempArr[i]=_cacheArr[i]; 70 } 71 WriteData(tempArr); 72 } 73 74 fStream.Close(); 75 fStream.Dispose(); 76 } 77 78 /// <summary> 79 /// 写入数据 80 /// </summary> 81 private void WriteData(ProfilterData [] arr) 82 { 83 binFormat.Serialize(fStream, arr); 84 _index=0; 85 } 86 }
1 using System.Collections; 2 using System.Collections.Generic; 3 using ProfilterDataNS; 4 using System.IO; 5 using System.Runtime.Serialization.Formatters.Binary; 6 7 public class AnalyzeData{ 8 public static List<ProfilterData> Analyze(string filePath) 9 { 10 MemoryStream ms = new MemoryStream(); 11 BinaryFormatter binFormat = new BinaryFormatter();//创建二进制序列化器 12 13 List<ProfilterData> profList=new List<ProfilterData>(); 14 15 using (FileStream fs= File.OpenRead("profilterData.bin")) 16 { 17 int offset=0; 18 while(fs.Position<fs.Length) 19 { 20 ProfilterData []dataArr=(ProfilterData[])binFormat.Deserialize(fs); 21 profList.AddRange(dataArr); 22 binFormat.Serialize(ms, dataArr);//序列化到内存流中 23 byte[] bt = ms.ToArray(); 24 offset=bt.Length;//获取偏移量 25 } 26 fs.Close(); 27 fs.Dispose(); 28 } 29 return profList; 30 } 31 }