C++MFC编程笔记day07 MFC的文件操作、序列化和保存

一 MFC的文件操作

1 相关类

CFile类-封装了文件句柄以及操作文件的API函数。

CFileFind类-提供文件查找功能。

2 CFile类的使用

2.1 打开或者新建文件

CFile::Open

2.2 文件读写

注意:1 文件指针位置 2 异常处理

CFile::Write

CFile::Read

CFile::SeekToBegin

2.3 关闭文件

CFile::Close

2.4 设置/获取文件属性

CFile::SetStatus/GetStatus

3 CFileFind类的使用

3.1 开始查找,返回值代表是否有文件存在

CFileFind::FindFile

3.2 获取找到的第一个文件信息,返回下一个文件是否存在

CFileFind::FindNextFile

3.3 获取文件信息和判断文件信息

CFileFind::GetXXX/IsXXX

3.4 结束查找

CFileFind::Close

例子:1 使用该类查找C:根目录下所有的文件和文件夹

注意:磁盘根目录中不存在.目录,只有在下一层目录中才

存在.目录。

2 使用该类查找C:下所有的文件和文件夹

2.1 递归,判断如果是目录,调用函数本身

strPath=find.GetFilePath()

2.2 排除.目录

IsDots

二 序列化

1 概念

将数据以二进制流的方式依次写入到文件和从文件中读取数据的过程。

2 相关类

CFile类

CArchive类-归档类,提供了具体的数据读写的功能。

引入该类的好处,一,可以设置读写时的缓冲区;二,支持多种数据

类型的读写。

3 读写操作

3.1 打开或者新建文件

CFile::Open

3.2 文件读写

3.2.1 定义CArchive类的对象

3.2.2 读写操作符函数

<< 写操作

>> 读操作

3.2.3 关闭

3.3 关闭文件CArchive类的对象

CFile::Close

三 对象的序列化(第6个机制)

引入对象的序列化,解决用户自定义类的对象的读写

1 概念

序列化对象(object store)

将对象的类的信息和对象的成员变量依次写入到文件的过程。

反序列化对象(object load)

从文件首先读取类的信息,创建对象,然后读取成员变量的值初始化

对象的过程。

结论:对象的序列化以运行时类信息和动态创建为基础的

2 使用

2.1 定义支持序列化的类 **

2.1.1 必须是CObject类的子类

2.1.2 添加序列化的声明宏和实现宏

2.1.3 重写虚函数 CObject::Serialize,在函数中,完成

类中的成员变量的序列化。

2.2 使用步骤与一般的数据类似

具体读写操作时,参数是对象的地址

3 原理

3.1 成员

_init_CStudent-结构体类型的成员对象,当定义该对象时,就会将

当前类的运行时类信息保存到应用程序中。

struct AFX_CLASSINIT

{

AFX_CLASSINIT(CRuntimeClass* pNewClass)

{

AfxClassInit(pNewClass);

{

//获取应用程序类的模块状态信息

AFX_MODULE_STATE* pModuleState = AfxGetModuleState();

AfxLockGlobals(CRIT_RUNTIMECLASSLIST);

//保存当前类的运行时类信息(classCstudent的地址)

pModuleState->m_classList.AddHead(pNewClass);

AfxUnlockGlobals(CRIT_RUNTIMECLASSLIST);

}

};

};

3.2 序列化对象的过程

ar.WriteObject(pOb);

{

//1 获取当前类的运行时类信息

CRuntimeClass* pClassRef = pOb->GetRuntimeClass();

//2 将类的信息写入到文件

WriteClass(pClassRef);

{

pClassRef->Store(*this);

{

//依次将类的版本,类名称长度以及类的名称写入文件

WORD nLen = (WORD)lstrlenA(m_lpszClassName);

ar << (WORD)m_wSchema << nLen;

ar.Write(m_lpszClassName, nLen*sizeof(char));

}

}

//3 调用Serilize函数存储对象的成员变量

((CObject*)pOb)->Serialize(*this);

{

//首先调用父类的序列化函数

CObject::Serialize( ar );

if (ar.IsStoring())//存储操作

{

ar<<m_strName<<m_nAge;

}

else//加载操作

{

ar>>m_strName>>m_nAge;

}

}

}

3.3 反序列化对象的过程

ar.ReadObject(RUNTIME_CLASS(CStudent));

{

//1 读取当前类的运行时类信息,得到运行时类信息变量的地址

ReadClass(pClassRefRequested, &nSchema, &obTag);

{

//  从文件中读取类的信息,比较并得到运行时类信息

pClassRef = CRuntimeClass::Load(...)

{

//读取类的名称

ar.Read(szClassName, nLen*sizeof(char));

//遍历链表,根据类的名称,查找运行时类信息

for (pClass = pModuleState->m_classList; pClass != NULL;

pClass = pClass->m_pNextClass)

{

//具体的比较类的名称

if (lstrcmpA(szClassName, pClass->m_lpszClassName) == 0)

{

return pClass;

}

}

}

}

// 2 根据得到的运行时类信息,动态创建对象

pOb = pClassRef->CreateObject();

//3 从文件中读取成员变量初始化新建的对象

pOb->Serialize(*this);

{

//首先调用父类的序列化函数

CObject::Serialize( ar );

if (ar.IsStoring())//存储操作

{

ar<<m_strName<<m_nAge;

}

else//加载操作

{

ar>>m_strName>>m_nAge;

}

}

}

程序示例:

新建win32控制台程序 ,添加afxwin.h头文件,设置包含MFC动态库

主程序代码如下:

// MFCfile.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <AFXWIN.H>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
//打印文件状态信息
void show_status(CFileStatus& status)
{
	printf("文件名:%s\n",status.m_szFullName);
	printf("大小:%g\n",status.m_size);
}
//打印空格 ,为了清楚地显示目录结构
void printspace(int n)
{
	if(n>0)
	{
		for(int i=0;i<n;i++) printf(" ");
	}
}
//文件读取和写入
void CFileTest()
{
	CFile file;//定义CFile对象
	//打开
	CString filename="MFCfile.txt";
	BOOL bresult=file.Open(filename,
		CFile::modeCreate|CFile::modeReadWrite);
	if(!bresult) return;//打开失败,直接返回
	try
	{
		CString str="Hello my cfile!";
		file.Write(str,str.GetLength());
		printf("写入成功\n");
		char sztxt[100]={0};
		file.SeekToBegin();//将文件指针移动到文件开头
		file.Read(sztxt,100);
		printf("读取成功,字符串:%s\n",sztxt);
		file.Close();

		CFileStatus status;
		//如果其他程序正在使用该文件,有可能出CFileException异常
		CFile::GetStatus(filename,status);//获取状态信息
		show_status(status);
		CTimeSpan span(7,0,0,0);//时间间隔,7天
		status.m_ctime-=span;//修改创建时间提前7天
		CFile::SetStatus(filename,status);//设置状态信息

	}
	catch (CMemoryException* e)
	{
		printf("内存出错\n");
	}
	catch (CFileException* e)
	{
		printf("文件操作出错\n");
	}
	catch (CException* e)
	{
		printf("其他错误\n");
	}
}
//文件查找
void CFileFindTest(CString strPath,int space=0)
{
	CFileFind cf;
	BOOL result=cf.FindFile(strPath+"\\*.*");//目录后要加通配符

	while(result)
	{
		result=cf.FindNextFile();
		CString filename=cf.GetFileName();
		printspace(space);
		if(cf.IsDirectory())
		{
			if(!cf.IsDots())
			{
				CString filepath=cf.GetFilePath();
				//printf("   subdir:%s\n",filepath);
				CFileFindTest(filepath,space+1);
			}
			printf("目录名:%s\n",filename);
		}
		else printf("文件名:%s\n",filename);

	}
	cf.Close();

}
//序列化(二进制),写入数据
void CArchiveStoreTest()
{
	CFile file;//定义CFile对象
	//打开
	CString filename="MFCfile1.txt";
	BOOL bresult=file.Open(filename,
		CFile::modeCreate|CFile::modeWrite);
	if(!bresult) return;//打开失败,直接返回
	CArchive ar(&file,CArchive::store);
	ar<<100<<12.46<<"hello archive!";//写入
	ar.Close();
	file.Close();
}
//序列化(二进制),读取数据
void CArchiveloadTest()
{
	CFile file;//定义CFile对象
	//打开
	CString filename="MFCfile1.txt";
	BOOL bresult=file.Open(filename,
		CFile::modeNoTruncate|CFile::modeRead);
	if(!bresult) return;//打开失败,直接返回
	CArchive ar(&file,CArchive::load);
	int i;
	double d;
	CString str;
	ar>>i>>d>>str;//读取
	ar.Close();
	file.Close();
	printf("%d,%f,%s\n",i,d,str);
}
//1 定义支持序列化的类
class CStudent:public CObject
{
public:
	virtual void Serialize( CArchive& ar );//重写虚函数
	CStudent(){}
	CStudent(CString strName,UINT nAge)
	{
		m_strName=strName;
		m_nAge=nAge;
	}
	void Show()
	{
		printf("姓名:%s\n",m_strName);
		printf("年龄:%d\n",m_nAge);
	}

public:
	CString m_strName;
	UINT m_nAge;
	//序列化的宏
	DECLARE_SERIAL(CStudent)
	/*  //宏内容
	_DECLARE_DYNCREATE(CStudent)
		AFX_API friend CArchive& AFXAPI
		operator>>(CArchive& ar, CStudent* &pOb);
	*/
};
IMPLEMENT_SERIAL(CStudent,CObject,1)
/* //宏内容
CObject* PASCAL CStudent::CreateObject()
{
	return new CStudent;
}
_IMPLEMENT_RUNTIMECLASS(CStudent, CObject, 1,
						CStudent::CreateObject)
AFX_CLASSINIT _init_CStudent(RUNTIME_CLASS(CStudent));

CArchive& AFXAPI operator>>(CArchive& ar, CStudent* &pOb)
{
	pOb =  (CStudent*) ar.ReadObject(RUNTIME_CLASS(CStudent));
	return ar;
}
*/
void CStudent::Serialize( CArchive& ar )
{
	//首先调用父类的序列化函数
	CObject::Serialize( ar );
	if (ar.IsStoring())//存储操作
	{
		ar<<m_strName<<m_nAge;
	}
	else//加载操作
	{
		ar>>m_strName>>m_nAge;
	}
}
//存入
void ObjectStore(CStudent & stu)
{
	CFile file;
	file.Open("C:\\stu.dat",
		CFile::modeCreate|CFile::modeWrite);
	CArchive ar(&file,CArchive::store);
	ar<<&stu;
	ar.Close();
	file.Close();
}
//读出
void ObjectLoad()
{
	CFile file;
	file.Open("C:\\stu.dat",CFile::modeRead);
	CArchive ar(&file,CArchive::load);
	CStudent *pStu=NULL;
	ar>>pStu;
	ar.Close();
	file.Close();
	if (pStu)
	{
		pStu->Show();
	}
}
int main(int argc, char* argv[])
{
    //CFileTest();
	//CFileFindTest("../../");
	CArchiveStoreTest();
	CArchiveloadTest();
	CStudent stu("student1",23);
    ObjectStore(stu);
	ObjectLoad();
	getchar();
	return 0;
}

C++MFC编程笔记day07 MFC的文件操作、序列化和保存

时间: 2025-01-05 17:32:42

C++MFC编程笔记day07 MFC的文件操作、序列化和保存的相关文章

C++MFC编程笔记day07 MFC单文档绘图保存、多文档绘图保存

完善绘图例子(day06中的),加上保存功能 1 设计和编写图形类 CShape 1.1 成员变量 CPoint m_ptBegin; CPoint m_ptEnd; UINT m_nType; 1.2 支持序列化 1.2.1 继承自CObject 1.2.2 添加序列化的声明宏和实现宏 1.2.3 重写虚函数Serilize(),在函数中,完成成员变量的序列化 2 由于保存多个图形,引入MFC的集合类CObArray,保存的是CObject 对象的地址. 3 图形数据需要保存到文档类中,在该类

C++MFC编程笔记day08 MFC对话框的使用

一 MFC对话框 1 分类 模式和非模式 2 相关类 CDialog类-父类是CWnd,本质上是一个窗口,对话框类的父类. CCommonDialog类以及子类-通用对话框,颜色对话框.文件对话框. 查找替换对话框.字体设置对话框.打印设置对话框和 打印对话框. CPropertyPage类-属性页对话框. 3 在Win32向导中,使用MFC的类创建对话框程序 3.1 模式对话框 3.1.1 创建和显示对话框 CDialog::DoModal() 3.1.2 对话框的关闭(无需用户处理) CDi

C++MFC编程笔记day03 MFC工具栏、状态栏、视图窗口

MFC工具栏 相关类: CToolBarCtrl - 父类是 CWnd  封装了工具栏控件相关操作 CToolBar - 父类是CControlBar  封装了工具栏和框架窗口之间的关系 工具栏使用: //把工具栏对象定义为 CMyFrameWnd成员: CToolBar toolbar; //在窗口创建时,加载工具栏资源 int CMyFrameWnd::OnCreate(LPCREATESTRUCT lpc) { toolbar.CreateEx(this,TBSTYLE_FLAT,WS_C

C++MFC编程笔记day02 MFC消息映射机制、菜单资源使用

机制3:MFC消息映射机制: 类内声明,类外定义宏,绑定消息处理函数 派生自CCmdTarget 类内声明宏:DECLARE_MESSAGE_MAP() 类外添加实现宏: BEGIN_MESSAGE_MAP(类名,父类名) END_MESSAGE_MAP() //数据结构 struct AFX_MSGMAP_ENTRY { UINT nMessage;   // 消息ID UINT nCode;      // 通知码 UINT nID;        // 控件ID或消息 UINT nLast

C++MFC编程笔记day01 MFC介绍、创建MFC程序和重写消息处理

一.MFC概念和作用 1.全称Microsoft Foundation Class Library,我们称为微软基础类库,封闭了绝大部分的win32 Api函数,C++语法中的数据结构,程序的执行流程 MFC就是一个库(动态库,静态库) MFC还是一个程序框架 2.为什么使用MFC 基于框架编程,提高工作效率,减少开发周期,节约开发成本. 二.几个重要的头文件 afx.h    -绝大部分类的声明头文件 afxwin.h -包含了afx.h和windows.h afxext.h -提供了扩展窗口

C++MFC编程笔记day06 MFC向导、MFC绘图类使用

MFC绘图 MFC绘图类包括绘图设备类和绘图对象类 1 绘图设备类 CDC类-父类是CObject,封装的是一般的绘图设备,例如:显示器, 打印机等. CWindowDC类-父类是CDC类,封装的是窗口对象,包括客户区和非 客户区. CClientDC类-父类是CDC类,封装的仍然是窗口,但是只包括客户区. CPaintDC类-父类是CDC类,封装的是窗口的客户区.但是,它只用 在窗口的WM_PAINT消息处理函数中. CMetaFileDC类-父类是CDC类,作用保存绘制命令. 2 使用 创建

C++MFC编程笔记day10 MF界面控件的使用2、属性页对话框、MFC线程

一 树型控件 1 相关类 CTreeCtrl-父类是CWnd,控件类. CTreeView-父类是CCtrlView,视图类.CTreeView=CView+CTreeCtrl CTreeView::GetTreeCtrl 2 CTreeCtrl的使用 对比CListCtrl:列表控件的每个数据项之间是平等关系,通过数据项 的索引值得到数据项的信息.树控件每个数据项称之为节点.节点之间 的关系包括父子关系和兄弟关系.通常通过节点句柄得到某个节点. 通常用来表示层次关系的数据. 2.1 设置控件的

C++MFC编程笔记day04 运行时类信息和窗口的动态、静态切分

运行时类信息 程序在运行时,获取对象类的信息及类的继承关系 实现: 1.定义类继承自CObject类. 2.类内声明宏DECLARE_DYNAMIC(),类外实现宏IMPLEMENT_DYNAMIC() 3.使用: BOOL IsKindOf(CRuntimeClass* pClass)//对象是否属于某个类 CRuntimeClass* GetRuntimeClass( );//获取对象运行时类信息,经常使用RUNTIME_CLASS(类名)代替. 示例: #include "stdafx.h

C++MFC编程笔记day09 MF界面控件的使用1

一 MFC控件 1 控件介绍 1.1 静态控件包括图片.静态文本和分组框.生成的控件的ID统一是 IDC_STATIC.很少程序中访问和操作,只是使用静态控件显示信息 1.2 编辑框控件,控件类是CEdit,通常使用它接收用户的输入,显示 信息给用户. 1.3 按钮控件包括一般按钮.复选按钮和单元按钮,控件类都是CButton 单选按钮注意,同一组的按钮Tab键顺序的编号连续(Ctrl+d  显示tab顺序),而且编号小的 按钮设置group属性,才能在同一个对话框中,实现多个单选按钮的 多个分