MFC总结(一):MFC中文件操作、查找与选择总结(2)

(二)CArchive类操作

     CArchive类实现数据的缓冲区读写,同时定义了类对象的存储与读取方案。 在文档视图编程,结合CList和CArray等可很方便的实现数据读写。

     (1)基本数据读写----显示创建CArchive对象

     A.  使用CArhive类之前,必须要有一个CFile文件对象,同时必须保证CArchive的操作必须是在CFile处于打开状态,且操作期间文件状态不会发生变化。

     B. 然后定义CArchive对象,将其与CFile对象关联,并指定其模式是用于缓冲区读还是写:

      CArchive ar (pFile,             //目标文件,CFile对象指针

                              nMode,        //操作方式, 读/写

                              nBufSize,    //指定缓冲区大小,默认为4096

                              lpBuf           //缓冲指针,默认为NULL,即从本地堆中取出一块内存空间,操作结束后自动释放

                            );

      C.对于基本数据类型,可直接使用operator >>operator <<进行数据读出和写入。这些数据类型BYTE、WORD、LONG、DWORD、float、double、int、short、char、unsigned u等。 对于CString对象也可使用。

       对于自定义的结构体数据类型,我们自己可以重载这两个运算符,一个示例如下。

    typedef struct test_st
    {
         float valueX;
         float valueY;

         //重载<<和>>运算符
        friend CArchive& AFXAPI operator <<(CArchive& ar, const test_st& info)
      {
            //保存
           ar<<info.valueX<<info.valueY;
           return ar;
      }
       friend CArchive& AFXAPI operator >>(CArchive& ar, test_st& info)
       {
            //读取
            ar>>info.valueX>>info.valueY;
            return ar;
       }
    }TEST;

     D. 使用ReadWrite可实现指定数据长度的数据写入/读取,这里的数据长度指的是字节数。

         使用WriteString可写入字符串,ReadString可读出一行字符。注意这里WriteString并不是写入一行字符串,WriteString写入的字符串时不会写入'\0',也不会自动写入'\n'。下面是来自MSDN的一个例子,相信能说明问题。

CFile myFile("myfile", CFile::modeCreate | CFile::modeReadWrite);
CString str1="String1", str2="String2", str;

// Create a storing archive.
CArchive arStore(&myFile, CArchive::store);

// Write str1 and str2 to the archive
arStore.WriteString( str1 );
arStore.WriteString( "\n" );
arStore.WriteString( str2 );
arStore.WriteString( "\n" );

// Close the storing archive
arStore.Close();

// Create a loading archive.
myFile.SeekToBegin();
CArchive arLoad(&myFile, CArchive::load);

// Verify the two strings are in the archive.
arLoad.ReadString( str );
ASSERT( str == str1 );
arLoad.ReadString( str );
ASSERT( str == str2 );

      E. IsLoading 和 IsStoring函数常用来判断是读取还是写入。

          Close函数用于切断与CFile对象的关联,在这之前会自动调用Flush将缓冲区数据写入存储媒质中。

     F. 在程序中,如果没有调用函数Flush(),那么真正将数据写入到物理磁盘是在调用函数Close()关闭时。因此,一些重要的数据需要使用Flush()函数立即写入文件,以防丢失。

      (2)类对象的读写

       A. 利用CArchive保存/加载一个类对象,则此类必须支持串行化。

      B. 自定义串行化类的五个步骤:

          ①继承CObject类;

          ②重载CObject类的Serialize成员函数;

          ③在类的.h文件中,进行串行化的声明:DECLARE_SERIAL(类名);

          ④定义一个无参数的构造函数;

          ⑤在类的.cpp文件中,进行声明:IMPLEMENT_SERIAL(类名, CObject, 版本号)

      C. 在自定义的类的Serialize成员函数下,使用上述(1)中的方法,保存/加载基本数据类型。如下。在需要文件操作的地方,直接调用该函数即可。

         void CXXXX::Serialize(CArchive &ar)
         {
              if (ar.IsStoring())
              {    //保存
                   //Add code....
              }
              else
              {   //读取

                 //Add code...
              }
         }

       D. 利用此方法,可实现数据的分布式保存。通常在文档视图编程时,我们在文档类下定义数据对象,然后在其Serialize函数下实现数据的保存/加载即可。

通常我们会定义一个容器,用来存放数据。例如,在我的项目中,我使用了

CTypedPtrList<CObList, CObject*> m_DataList;

这是一个链表,里面元素为CObject类对象的指针,当我们自定义了支持串行化的类后,就可以把数据加入到这个链表中,很方便的实现数据管理和存储。


     最后推荐两个网址,

        http://hi.baidu.com/andywangcn/blog/item/f892b43fa42dc13270cf6cde.html     里面有个例子,大家可以看看。

        http://hi.baidu.com/bin545/blog/item/1a6a58af96d164fdfaed5028.html    里面对CArchive类的成员函数的源码做了部分分析,可以深入研究。

     未完,待续。。。



发布了37 篇原创文章 · 获赞 204 · 访问量 44万+

猜你喜欢

转载自blog.csdn.net/zwgdft/article/details/7107276