📄 13.1 使用 carchive类对文件进行读写操作.txt
字号:
13.1 使用 CArchive类对文件进行读写操作
本章首先介绍一种新的读写文件的方式:使用 MFC提供的 CArchive类来实现。 CArchive类没有基
类。我们知道,一个对象一旦被构造,它就存活于内存中了,当其生命周期结束后,该对象就要被
销毁。我们可以利用 CArchive类将对象数据保存到永久设备(例如磁盘文件)上,这样,即使应用程
序关闭,再次重启后,仍可以从磁盘文件中读取对象数据,然后在内存中重新构建相应的对象。让
对象数据持久性的过程就称之为串行化(或称为序列化〉。
读者可以认为一个 CArchive对象就是一种二进制流。就像一个输入/输出流一样,一个 CArchive
对象与一个文件相关,并允许带缓冲机制的数据写入和读取。与输入/输出流不同的是,后者处理的
是 ASCII码字符序列,而一个 CArchive对象以一种有效的、非冗余的格式处理二进制对象数据。
在程序中使用 CArchive对象时有几点需要注意,首先是在创建 CArchive对象之前必须先创建一个
CFile类或其派生类对象,并且因为存档对象既可以用来加载数据,也可以用来保存数据,所以必须
确保这个 CFile类对象的打开方式与该存档(*'chive)对象的加载/保存状态相一致。当构造了一个
CArchive对象后,就可以将它与一个代表某个打开文件的 CFile类对象或其派生类对象相关联,但
应注意,一个文件(即 CFile对象)只能与
→个活动的存档对象相关联。
CArchive对象不仅可以处理基本类型的数据,还可以处理 CObject类的派生类对象。 CArchive类重
载了提取(>>)和插入(<<)操作符,它们既支持基本类型,也支持'CObject类的派生类,为用户提供
了一种方便的对象存档编程接口。其中提取(>>)操作符是从存档对象加载 CObject类型和基本类型
的数据:插入(<<)操作符是将 CObject类型和基本类型的数据存储到存档对象中。在 CArchive类中,
这两种操作符分别都有多种重载形式(如例 13-1代码所示)。通过这些重载的函数,我们可以利用
CArchive对象来完成文件的读写操作。
例13-1
friend CArchive& operator >>( CArchive& ar, CObject *& pOb );.
CArchive& operator >>( BYTE& by );
CArchive& operator >>( WORD& w );
CArchive类的构造函数的原型声明如下所示:
CArchive( CFile* pFile, UINT nMode , int nBufSize = 4096 , void* lpBuf = NULL ) ;
该构造函数具有三个参数,其含义分别如下所述:
. pFile
指向文件对象的指针,该文件对象是持久数据的最终未源或目的地。
. nMode
. 指定对象是被用来加载的,还是用来保存的标志。取值可以是如表 13.1所示值之一。
表13.1 nMode参数取值
取值 说明
CArchive::load 从存档对象中装载数据。要求CFile对象具有读取访问许可
CArchive::store 将数据保存到存档对象中。要求CFiJe对象具有写入访问许可
CArchive::bNoFlushOnDelete 禁止存档对象析构时自动调用存档对象的F\ush操作。如果设置了此
标志,那么在存档 对象析构前必须显式地调用其Close函数。否则,数据将被破坏
. nBufSize
指定内部文件缓冲区的大小,以字节为单位。默认的缓冲区大小是4096字节。
. lpBuf
可选指针,指向用户提供的大小为nBufSize的缓冲区。如果未指定这个参数,那么存档对象将从应
用程序的局部堆中分配一块缓冲区,并且该对象销毁时将释放这块内存。但是存档对象并不会释放
用户提供的缓冲区。所以,如果指定了这个参数,就要手工地释放这块内存。
下面将介绍使用CArchive类读写文件的具体过程。为方便起见,本章将在第11章己有程序的基础上
继续添加功能。首先打开第 11章己有的Graphic工程,为该工程的主菜单增加一个子菜单,菜单名
称为:文件操作。然后,为其添加两个菜单项,并分别为它们添加相应的命令响应函数,本例让
CGraphicView类接收这些菜单项的命令响应。这两个新添菜单项的E、名称,以及相应的响应函数名
称如表13.2所示。
表 13.2新添菜单项属性及晌应函数名称
ID 菜单名称 响应函数
IDM FILE WRITE 写入文件 OnFileWrite
IDM FILE READ 读取文件 OnFileRead
然后在OnFileWrite函数中添加如例 13-2所示的代码。 ~IJ 13-2
void CGraphicView ; ;OnFileWrite ()
// TODO: Add your command handler code here
//构造CFile文件对象
CFile file(" 1. txt" , CFile::modeCreate | CFile::modeWrite};
//构造存档对象
CArchive ar(&file, CArchive::store);
int i=4;
char ch=' a ' ;
float f=1.3f;
CString str(nhttp://www.sunxin.orgn};
//保存数据
ar<<i<<ch<<f<<str;
在上述例 13-2所示代码中,首先构建了一个CFile类型的文件对象: file。接着构造了一个CArchive
类型的对象:ar,其构造函数的第一个参数就是与该存档对象相关联的文件对象 (file),第二个参数
是模式标志,对于保存操作,应该选择CArchive::store标志。因为 CArchive类的构造函数的后两
个参数都有默认值,所以不用为它们赋值。接下来,定义了一个整型变量(0、一个字符型变量 (ch)、
一个浮点型变量(f)和一个CString类型的对象 (s位),并为它们赋了相应的值。最后,调用CArchive
对象重载的插入(<<)操作符将数据保存到文件中。
在C/C++中,浮点数在默认情况下被定义为double类型。如果希望指定
float类型的数值,需要在该数值后要加上字母f。
运行Graphic程序,单击【文件操作写入文件】菜单项,然后,在Graphic程序所在目录下可以发
现多了一个名为"1.四"的文件。下面再利用CArchive类实现对文件的读取操作,在OnFileRead函数
中添加如例 13-3所示代码。
例3-3
void CGraphicview::OnFileRead(}
// TODO: Add your command handler code here
//构造CFile文件对象
CFile file ( "1. txt n, CFile: :modeRead) ;
//构造存档对象
CArchive ar(&file,CArchive::load);
int i;
char ch;
float f;
CString str;
CString strResult;
//读取数据
ar>>i>>ch>>f>>str;
strResult . Format( "%d,%c,%f.%S" ,i,ch, f,str) ;
MessageBox(strResult) ;
在上述例 13-3所示代码中,同样地,首先定义了一个 CFile类型的文件对象: file , 并且该文件
对象按照读取方式 ( CFile::modeRead )打开。接着,构造了一个 CArchive对象 :ar,其构造函数
的第一个参数就是与该存档对象相关联的文件对象,第二个参数是模式标志,因为现在是加载数据,
所以将其设置为 CArchive ::load。接下来,定义了一个整型变量(i)、一个字符型变量 ( ch )、
一个浮点型变量(f)和一个 CString类型的对象 ( str ) , 用于保存从文件中读取的数据。再定义
了一个 CString类型的对象 : strResult,用来保存读取数据格式化后的结果。这时就可以利用
CArchive类提供的提取操作符 (>>)加载数据。注意,对象保存的顺序和提取的顺序必须一致。然后
对读取到的数据进行格式化,最后使用 MessageBox函数将所读取的数据显示出来。
运行 Graphic程序,单击【文件操作_读取数据】菜单项,程序即可弹出如图 13.1所示消息框,可
以看到读取的结果是正确的。
图 13 .1显示读取数据的消息框
通过上面的例子,读者可以发现,对存档对象来说,无论什么类型的数据,都可以使用插入C<d操作
符将其保存到文件中,使用提取 (>>)操作符从文件中加载这些数据,操作非常方便。
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -