MyException - 我的异常网
当前位置:我的异常网» 编程 » C++MFC编程札记day07 MFC的文件操作、序列化和保存

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

www.MyException.Cn  网友分享于:2014-08-05  浏览:0次
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;
}




文章评论

科技史上最臭名昭著的13大罪犯
科技史上最臭名昭著的13大罪犯
“肮脏的”IT工作排行榜
“肮脏的”IT工作排行榜
程序员和编码员之间的区别
程序员和编码员之间的区别
Google伦敦新总部 犹如星级庄园
Google伦敦新总部 犹如星级庄园
程序员最害怕的5件事 你中招了吗?
程序员最害怕的5件事 你中招了吗?
每天工作4小时的程序员
每天工作4小时的程序员
做程序猿的老婆应该注意的一些事情
做程序猿的老婆应该注意的一些事情
60个开发者不容错过的免费资源库
60个开发者不容错过的免费资源库
聊聊HTTPS和SSL/TLS协议
聊聊HTTPS和SSL/TLS协议
如何区分一个程序员是“老手“还是“新手“?
如何区分一个程序员是“老手“还是“新手“?
为啥Android手机总会越用越慢?
为啥Android手机总会越用越慢?
 程序员的样子
程序员的样子
我的丈夫是个程序员
我的丈夫是个程序员
我跳槽是因为他们的显示器更大
我跳槽是因为他们的显示器更大
Web开发者需具备的8个好习惯
Web开发者需具备的8个好习惯
为什么程序员都是夜猫子
为什么程序员都是夜猫子
鲜为人知的编程真相
鲜为人知的编程真相
10个调试和排错的小建议
10个调试和排错的小建议
程序员必看的十大电影
程序员必看的十大电影
10个帮程序员减压放松的网站
10个帮程序员减压放松的网站
一个程序员的时间管理
一个程序员的时间管理
2013年美国开发者薪资调查报告
2013年美国开发者薪资调查报告
我是如何打败拖延症的
我是如何打败拖延症的
编程语言是女人
编程语言是女人
什么才是优秀的用户界面设计
什么才是优秀的用户界面设计
当下全球最炙手可热的八位少年创业者
当下全球最炙手可热的八位少年创业者
老程序员的下场
老程序员的下场
老美怎么看待阿里赴美上市
老美怎么看待阿里赴美上市
漫画:程序员的工作
漫画:程序员的工作
写给自己也写给你 自己到底该何去何从
写给自己也写给你 自己到底该何去何从
旅行,写作,编程
旅行,写作,编程
看13位CEO、创始人和高管如何提高工作效率
看13位CEO、创始人和高管如何提高工作效率
Java程序员必看电影
Java程序员必看电影
程序员眼里IE浏览器是什么样的
程序员眼里IE浏览器是什么样的
不懂技术不要对懂技术的人说这很容易实现
不懂技术不要对懂技术的人说这很容易实现
5款最佳正则表达式编辑调试器
5款最佳正则表达式编辑调试器
要嫁就嫁程序猿—钱多话少死的早
要嫁就嫁程序猿—钱多话少死的早
程序员的一天:一寸光阴一寸金
程序员的一天:一寸光阴一寸金
“懒”出效率是程序员的美德
“懒”出效率是程序员的美德
那些性感的让人尖叫的程序员
那些性感的让人尖叫的程序员
程序员应该关注的一些事儿
程序员应该关注的一些事儿
Java 与 .NET 的平台发展之争
Java 与 .NET 的平台发展之争
2013年中国软件开发者薪资调查报告
2013年中国软件开发者薪资调查报告
程序员周末都喜欢做什么?
程序员周末都喜欢做什么?
程序猿的崛起——Growth Hacker
程序猿的崛起——Growth Hacker
那些争议最大的编程观点
那些争议最大的编程观点
Web开发人员为什么越来越懒了?
Web开发人员为什么越来越懒了?
总结2014中国互联网十大段子
总结2014中国互联网十大段子
程序员的鄙视链
程序员的鄙视链
软件开发程序错误异常ExceptionCopyright © 2009-2015 MyException 版权所有