平常我们使用文件存储程序数据时,一般需要将数据转换为文本等存储,等到需要使用的时候再从文件读取,然后重新构建类或结构或数组等对象。这样的转换和重建即浪费了时间效率不够高又导致容易出错,其实最近由于研究二进制文件的存取,我找到了序列化存取的方法。
序列化存取可以做到类对象、结构、数组等内存实体整体保存为二进制的文件,而不需转换,读取的时候,通过反序列化直接从文件构建对象,而不需要重新通过转换而来的数据构建,这样既节省了转换时间,运行速度又比较快。
简要说明一下,序列化主要是通过实现System.Runtime.Serialization.IFormatter接口的System.Runtime.Serialization.Formatters.Binary.BinaryFormatter类来实现的,其中的void Serialize(Streamst, object ob)来实现序列化,这个函数就可以将object对象ob序列化为二进制流输入给Stream流st,这个方法有重载,具体看MSDN,但对于我们只想简单序列化,这样写也就够了。object
Deserialize(Stream st)这个方法可以实现反序列化,从给定的Stream流st中反序列化出一个object对象,只需强制转换为目标对象就可以了。
为了说明问题,新建了一个示例工程(winForm程序),就一个界面,实现一个类的存和取如下(如果要序列化存储结构和数组只需要将Person对象换成相应对象即可,另外设计器自动生成的代码没有贴出来):
(程序调试截图)
(存储的二进制文件在VS中打开的截图)
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.IO; namespace 序列化的二进制文件存取 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } /// <summary> /// 存储文件位置 /// </summary> public static string savePath = "序列化存储文件.data";//指定存储在程序启动文件夹下的"序列化存储文件.data"内 /// <summary> /// 存 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void button_Save_Click(object sender, EventArgs e) { //新建Person类对象 Person newPerson = new Person(); newPerson.name = textBox_name.Text; newPerson.age = Convert.ToInt32(textBox_age.Text); newPerson.grade = Convert.ToInt32(textBox_grade.Text); //这个对象用于序列化对象 System.Runtime.Serialization.Formatters.Binary.BinaryFormatter binaryFormatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter(); ////或者用这个接口创建实例也可以 //System.Runtime.Serialization.IFormatter binaryFormatter // = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter(); ////序列化person对象newPerson,先转化为二进制再存为文件 //System.IO.MemoryStream ms = new System.IO.MemoryStream(); //binaryFormatter.Serialize(ms, newPerson); //byte[] buffer = ms.GetBuffer(); //System.IO.Stream st = new System.IO.FileStream(savePath, System.IO.FileMode.Create); //st.Write(buffer, 0, buffer.Length); //st.Close(); //序列化person对象newPerson并存为文件 System.IO.Stream st = new System.IO.FileStream(savePath, System.IO.FileMode.Create);//新建文件流 binaryFormatter.Serialize(st, newPerson);//序列化类对象,并输入流 st.Close(); } /// <summary> /// 取 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void button_Read_Click(object sender, EventArgs e) { //这个对象用于反序列化对象 System.Runtime.Serialization.Formatters.Binary.BinaryFormatter binaryFormatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter(); //浏览存储的对象文件 OpenFileDialog op=new OpenFileDialog(){Filter="PerSon类文件(*.data)|*.data",InitialDirectory=Application.StartupPath}; op.ShowDialog(); if (System.IO.File.Exist(op.FileName))//如果浏览到文件 { System.IO.Stream st = new System.IO.FileStream(op.FileName, System.IO.FileMode.Open);//指向数据文件的二进制流 Person per = (Person)binaryFormatter.Deserialize(st);//反序列化,得到的是一个object对象,需要强制转换 textBox_Show.Text = per.ToString();//显示对象信息 st.Close(); } else textBox_Show.Text = "没有相关文件!"; } } /// <summary> /// 类示例 /// </summary> [Serializable]//加上这个属性后此类创建的对象才能被序列化 class Person { public string name { set; get; } public int age { set; get; } public int grade { set; get; } public override string ToString() { return "名字:" + name.ToString() + "\r\n年龄:" + age.ToString() + "\r\n年级:" + grade.ToString(); } } }