C#以二进制方式存取文件

    昨天讨论了怎么把内存对象序列化然后以二进制文件的形式储存和读取。但是实际编程应用中,不是所有情况下都需要将整个对象写到文件里,如果我们只想要写部分数据(比如一个字符串或者一个数字等)怎么办呢?这时就只需用到System.IO名称空间里的BinaryWriterBinaryReader类。

    研究过前辈写的一些C++/C的二进制文件读取的代码后,我发现C#在二进制文件读写这方面处理得更加聪明一些。C/C++主要是通过内存位置精确控制读取对应位,而在C#中实际上你不必考虑这些,只需要知道你存入数据的顺序,读取时按照存入顺序依次读取就可以了。比如说你用BinaryWriter对象的void Write(int i)函数存入了一个int32位的数据,再用void Write(string str)存入了一个字符串,再用void Write(double d)存入了一个双精度浮点数,在读取的时候,只需要依次用BinaryReader对象的int ReadInt32()、string ReadString()、double ReadDouble()依次读取数据流就可以获得intstingdouble三个类型的数值。至于数据流从哪一位开始读到哪一位结束都不用你关心,都交给C#自己去判断吧。当然,存取顺序不一致会导致读出意外的值或者什么都读不出来,或者超出数据流范围。

    另外如果你坚持像C++/C那样自己控制读写位置的话,也可以通过Streamlong Seek(int Offset,SeekOrigin origin)函数来设置。

以下示例代码(只给出了关键代码):

        string path = Application.StartupPath + "\\data.db";//二进制文件路径
        private void button1_Click(object sender, EventArgs e)//存为文件
        {
            Person per = new Person() { name = "文文lele", age = 12, height = 1.50 };//实例化一个数据

            Stream st = new FileStream(path, FileMode.Create);
            BinaryWriter bw = new BinaryWriter(st);
            bw.Write(per.age);//先int
            bw.Write(per.name);//再string
            bw.Write(per.height);//最后double
            bw.Close();
            st.Close();
        }

        private void button2_Click(object sender, EventArgs e)//读取文件
        {
            Stream st = new FileStream(path, FileMode.Open);
            BinaryReader br = new BinaryReader(st);

            Person pr = new Person();//一个未被具体指明的

            pr.age = br.ReadInt32();//先int
            pr.name = br.ReadString();//再string
            pr.height = br.ReadDouble();//最后double
            textBox1.Text = pr.ToString();//最后文本框会显示:名字:文文lele\r\n年龄:12\r\n身高1.50
            br.Close();
            st.Close();
        }
    }

    class Person
    {
        public string name { set; get; }
        public int age { set; get; }
        public double height { set; get; }
        public override string ToString()
        {
            return "名字:" + name.ToString() + "\r\n年龄:" + age.ToString() + "\r\n身高:" + height.ToString();
        }
    }

如果想要使用Stream的long Seek(int Offset,SeekOrigin origin)函数来设置从哪开始读,则读取的代码应该改为如下:

        private void button2_Click(object sender, EventArgs e))//读取文件
        {
            Stream st = new FileStream(path, FileMode.Open);
            BinaryReader br = new BinaryReader(st);

            Person pr = new Person();//一个未具体化的例子

            st.Seek(4, SeekOrigin.Begin);//因为二进制文件中存储的第一个是32位的年龄(整型默认32位),占4字节,所以名字从第4字节开始(8位为1字节,32位即4字节)
            pr.name = br.ReadString();

            st.Seek(0, SeekOrigin.Begin);//年龄记录在开始处
            pr.age = br.ReadInt32();

            st.Seek(-8, SeekOrigin.End);//身高是64位的双精度浮点型,占8字节,放在最后,所以从后往前数8个字节
            pr.height = br.ReadDouble();
            textBox1.Text = pr.ToString();//最后文本框会显示:名字:文文lele\r\n年龄:12\r\n身高1.50和第一种方法没有变
            br.Close();
            st.Close();
        }

两种读法或得相同的效果,这里为了使string类型长度固定可以放在最后,也可以使用StringBuilder建立指定长度字符串。

 

你可能感兴趣的:(C#以二进制方式存取文件)