什么是持久化(Persistence)

 

        无论何时运行上面的SRS程序,我们声明和初始化的任意对像(或值类型)都会“存活”在内存中。当程序结束运行后,分配程序的所有内存将会被操作系统回收,应用程序创建的所有内部状态都会失去,除非以某种方式把它们保存起来——而且是永久性地保存起来。

        利用不同的API,C#提供了多种可供选择的数据持久化方案。

1、在System.Data、System.Data.Odbc和System.Data.OleDb命名空间中的编程元素,允许我们将数据保存在一个ODBC或OLE DB数据库中。

2、可以将对象输出成一种特殊的二进制形式,这种形式被称作C#序列化对象(serialized object),适用于在网络中传输。

3、也可以将信息存储为相当直截了当的、“人类可读的”ASCII码数据形式,可以是下面的其中一种:

     有层次结构的数据,例如XML语言标准。在这种数据里面放入信息——“内容”——用自定义的标签来描述信息如何存放。

     简单地以制表符或逗号作为分隔符的面向记录(record-oriented)的数据;在SRS应用程序中,我们展示了最基础的持久化形式——面向记录的ASCII码持久化文件;然而,同样的设计原理对其他的持久化性有效。例如:

      把保存对象的具体过程封装在一个对象的方法中,客户代码无需了解细节;

      保证保存对象的方法的灵活性,这样,在修改代码的具体实现时,不会影响到整个应用程序。

      当发生异常时正确且漂亮地处理错误;因为数据的持久化需要与外部文件系统、数据库系统,和/或网络打交道,在此过程中很可能会出现失败的情况。

当然,文件持久化和硬币一样有两面:将对象的状态写到文件,然后再读出来。下面简单讨论这两种操作的C#是实现手法。

 

FileStream类

    FileStream对象时C#对象的一个类型,它懂得如何打开文件,并向文件中每次写一个字节数据。

    FileStream类的构造器的开头如下所示:

public FileStream(string filename,int mode)

例如,

FileStream fs = new FileStream("data.dat",FileMode.Open);

其中mode是FileMode类中定义的几个常量:

FileMode.Open:以读或写得模式打开一个文件;如果文件不存在或者无法打开,将抛出一个FileNotFoundException异常;

FileMode.Create:打开一个用于写得新文件;如果指定文件名的文件已经存在,或者因为其他原因无法创建文件——例如文件夹是写保护的——将会抛出一个IOException异常;

FileMode.Append:打开一个用于写的已存在的文件,新增数据会添加到文件的最后;如果指定文件无法找到,将会被抛出一个FileNotFoundException异常;

FileMode.CreateOrAppend:如果发现指定文件名的文件存在,则打开文件往里面些数据;否则,在文件夹中创建一个新文件。如果文件因为某些原因无法创建——例如文件夹被写保护——IOException异常将会被抛出。

 

从文件中读取数据

从一个ASCII 文件中逐个读取记录的基本手段,与两种C#对象类型有关——FileStream对象和StreamReader对象。

1、首先,创建一个FileStream类型对象,前面介绍过,它懂得怎样打开文件及每次从文件中读取一个字节。

2、接下来,将Filestream对象作为参数传递给一个StreamReader构造器,StreamReader是一种有效地包装了FileStream 类的复杂对象类型。StreamReader类的ReadLine方法懂得如何收集,或者说缓冲(buffer)FileStream依次读入的单个字符,直到行结束符为止,此时StreamReader将完整的一行/一条记录数据交回给客户代码。

StreamReader类也被定义在System.IO命名空间中。

下例演示了如何从一个文件中读取数据;

using System.IO;

public class IOExample
{
    static void Main()
    {
        //声明用来读数据的对象引用
        FileStream fs;
       StreamReader srIn;

        //读得过程需要放在try-catch块中
        try{
          //创建一个FileStream...
          fs= new FileStream("data.dat",FileMode.Open);


          //....在此FileStream基础上创建StreamReader.
          srIn = new StreamReader(fs);
         
          //从文件中读出第一行
           string line = srIn.ReadLine();
        
         // 只要此行不空,继续读!
           while(line!=null)
         {
          //伪代码
             Process the most recently read line
           //读另一行(当文本结束后被设为空)
             line = srIn.ReadLine();
        }
         // 关闭StreamReader,这样FileStream也会关闭
          srIn.Close();
      }
      catch(IOException ioe){
          执行异常操作...细节从略
      }
    }
}

对上例的解释:

1、因为在文件I/O操作是极有可能发生错误——要开发的文件可能不存在,要写得数据文件可能只读,等等——必须将代码放在一个try代码中,并提供处理潜在IOException异常的捕获代码;

2、我们打算从一个已存在文件中读数据,因此把FileMode.Open常量传入FileStream构造器:

  fs = new FileStream("data.dat",FileMode.Open);

3、将FileStream作为参数传递给StreamReader的一个新实体,从而能够用StreamReader类中的ReadLine方法从文件中一次读取一行:

   srIn= new StreamReader(fs);

4、使用StreamReader的ReadLine方法,从文件中每次读取一行数据/记录:

  string line = stIn.ReadLine();

只要该方法没有返回一个null 值 ——null值表示到达文件尾——就可以继续从文件中读取一条合法数据:

  //只要次行不为空,继续读

  while (line !=null) {...}

5、在while循环中,必须记得读取文件的下一条记录,这样才能保证不进入死循环:

   line = stIn.ReadLine();

6、最后,必须记得关闭StreamReader对象,这样同时会关闭FileStream对象;stIn.Close();

  在读取完成后关闭StreamReader 非常重要,因为:

  这样做,文件才不会对后续访问保持打开/上锁状态;

  这样做,整个应用程序才不会超过(与平台有关的)最大可打开文件数限制。

  这样做,能够释放不使用对象,让它们进入垃圾回收过程。

   

向文件写数据

往一个ASCII文件中写记录的一种C#实现手段,和读文件类似。

1、再次创建一个FileStream对象:在构造器中指明合适的打开模式;FileStream可以用来覆盖原文件(FileMode.Open),在已存在文件尾部添加(FileMode.Append),创建一个新文件(FileMode.Create),或者合并“打开”和“创建”模式(FileMode.OpenOrCreate)。

2、接着,将FileStream对象作为参数传入StreamWriter构造器。StreamWriter是一个包装FileStream的复杂对象类型。StreamWriter类的WriteLine方法知道如何传递一条完整的记录/一行数据,然后通过其封装的FileStream对象每次向文件写一个字节。

StreamWriter类从Textwriter类继承了WriteLine方法。它的工作方式与你已经熟知的Console.WriteLine方法类似,唯一的区别是前者会将文本输出到文件中,而后者显示在命令窗口。Console.WriteLine还定义了一个Write方法,和Console.Write方法类似。

 StreamWriter类被定义在System.IO命名空间中。

using System.IO;

public class IOExample2
{
    static void Main(){
       FileStream fs;
       StreamWriter sw;
       
       //写操作应该放在try-catch代码中
        try{
           //创建一个FileStream..
          fs = new FileStream("data.dat",FileMode.OpenOrCreate);
           //...在此FileStream基础上创建StreamWriter.
           sw = new StreamWriter(fs);
          
            //伪代码
              while(still want to print more){
            sw.WriteLine(Whatever string data we wish to output);
            sw.Close();

            }
            catch(IOException ioe)
           {
                //执行异常操作。
           }
  
       }
    }
}


 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值