现在的位置: 首页 > 综合 > 正文

C#通过序列化的方式存读类、结构、数组等为二进制文件

2013年08月09日 ⁄ 综合 ⁄ 共 3158字 ⁄ 字号 评论关闭

平常我们使用文件存储程序数据时,一般需要将数据转换为文本等存储,等到需要使用的时候再从文件读取,然后重新构建类或结构或数组等对象。这样的转换和重建即浪费了时间效率不够高又导致容易出错,其实最近由于研究二进制文件的存取,我找到了序列化存取的方法。

序列化存取可以做到类对象、结构、数组等内存实体整体保存为二进制的文件,而不需转换,读取的时候,通过反序列化直接从文件构建对象,而不需要重新通过转换而来的数据构建,这样既节省了转换时间,运行速度又比较快。

简要说明一下,序列化主要是通过实现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();
        }
    }
}

 

抱歉!评论已关闭.