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

来源:互联网 发布:windows核心编程 第6版 编辑:程序博客网 时间:2024/05/06 10:34

(二)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 archivearStore.WriteString( str1 );arStore.WriteString( "\n" );arStore.WriteString( str2 );arStore.WriteString( "\n" );// Close the storing archivearStore.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类的成员函数的源码做了部分分析,可以深入研究。

     未完,待续。。。