文件操作
序列化基本类型
以二进制流形式读写硬盘文件,但这种方式效率高。
- CFile 文件操作类,完成硬盘文件读写操作。
- CArchive 归档类,完成内存数据操作。
CFile:
- CFile::Open
- CFile::Write / Read
- CFile::Close
- CFile::SeekToBegin / SeekToEnd / Seek
void fun()
{
CFile file;
file.Open("C:/path/to/file", CFile::modeReadWrite | CFile::modeCreate);
char str[] = "hello file";
file.Write(str, strlen(str));
file.SeekToBegin();
char buf[256] = { 0 };
long nLen = file.Read(buf, 255);
std::cout << buf << " : " << nLen << std::endl;
}
序列化机制使用
在内存中使用 /0 标识字符串的结束;在序列化的文件中,在字符串的前面用一个字节加上长度
图中的特殊符号就保存了字符串的长度
void store()
{
CFile file;
file.Open("C:/file", CFile::modeReadWrite);
CArchive ar(&file, CArchive::store);
ar << 1L << 88.5 << "string";
ar.Close();
file.Close();
}
void load()
{
CFile file;
file.Open("C:/file", CFile::modeReadWrite);
CArchive ar(&file, CArchive::load);
long a; float b; CString c;
ar >> a >> b >> c;
std::cout << a << b << c << std::endl;
ar.Close();
file.Close();
}
序列化过程:
- ar 对象维护一个缓冲区
- 将各个数据依次序列化到ar维护的缓冲区中,并将 m_lpBufCur 指针移动响应字节
- 如果ar维护的缓冲区不足,则将ar维护的缓冲区的数据写入硬盘文件,并重置 m_lpBufCur 为开始指向
- 当关闭ar对象时,将ar对象维护的缓冲区数据写入硬盘文件,释放ar维护的缓冲区
反序列化过程:
- ar 对象维护一个缓冲区
- 当反序列化第一个数据时,将文件数据全部读取到ar维护的缓冲区中,并将第一个数据反序列化到第一个变量,并将 m_lpBufCur 移动相应字节数
- 依次反序列化每个数据到变量中
- 当关闭ar对象时,释放ar维护的缓冲区
序列化类对象
序列化对象就是将对象的各个成员变量序列化,但与直接序列化各个字段不同,还会保存类名、类大小、类版本,然后保存字段。
要求:
- 必须派生自
CObject
- 类内必须添加声明宏
DECLARE_SERIAL(theClass)
- 类外必须添加实现宏
IMPLEMENT_SERIAL(theClass, baseClass, 1)
- 类必须重写虚函数
Serialize
class CMyDoc : public CDocument
{
DECLARE_SERIAL(CMyDoc) // 包含了 DECLARE_DYNCREATE(CMyDoc) 用于反序列化时动态生成对象
public:
CMyDoc(int age = 0, float score = 0.0, CString name = "") : m_age(age), m_score(score), m_name(name) {}
int m_age;
float m_score;
CString m_name;
virtual void Serialize(CArchive& ar);
};
IMPLEMENT_SERIAL(CMyDoc, CDocument, 1) // 包含了 IMPLEMENT_DYNCREATE(CMyDoc, CDocument)
void CMyDoc::Serialize(CArchive& ar)
{
if (ar.IsStoring())
{
ar << m_age << m_score << m_name;
}
else
{
ar >> m_age >> m_score >> m_name;
}
}
void store()
{
CFile file;
file.Open("C:/file", CFile::modeReadWrite);
CArchive ar(&file, CArchive::store);
CMyDoc data(1, 5.5, "zhangsan");
ar << &data; // 序列化对象就是将对象的各个成员变量序列化
ar.Close();
file.Close();
}
void load()
{
CFile file;
file.Open("C:/file", CFile::modeReadWrite);
CArchive ar(&file, CArchive::load);
CMyDoc* pData = NULL;
ar >> pData;
ar.Close();
file.Close();
std::cout << pData->m_age << pData->m_score << pData->m_name << std::endl;
}
对话框
- 模式对话框(假,使用 EnableWindow 伪造)
- 无模式对话框
无模式对话框架构使用 CDialog CWinApp
- 添加 Dialog 资源
- 定义一个自己的对话框类,管理对话框资源,派生自
CDialog
或CDialogEx
均可
// 这份代码将对话框做为主窗口,点击“确定”按钮后窗口消失但进程依然存在,因为父类中虚函数使用了 EndWindow 隐藏窗口
#include <afxwin.h>
#include "resource1.h"
class CMyDlg : public CDialog
{
DECLARE_MESSAGE_MAP()
public:
void OnCancel();
};
BEGIN_MESSAGE_MAP(CMyDlg, CDialog)
ON_COMMAND(IDCANCEL, OnCancel)
END_MESSAGE_MAP()
void CMyDlg::OnCancel()
{
this->DestroyWindow();
}
class CMyWinApp : public CWinApp
{
public:
virtual BOOL InitInstance();
};
BOOL CMyWinApp::InitInstance()
{
CMyDlg* pdlg = new CMyDlg;
pdlg->Create(IDD_DIALOG1);
m_pMainWnd = pdlg;
pdlg->ShowWindow(SW_SHOW);
pdlg->UpdateWindow();
return TRUE;
}
CMyWinApp theApp;
执行过程:
- 获得应用程序类对象theApp的地址
- 利用theApp地址调用InitApplication,初始化当前应用程序的数据
- 利用theApp地址调用InitInstance函数,在函数中创建无模式对话框并显示
- 利用theApp地址调用CWinApp的Run函数进行消息循环
- 如果没有消息,利用theApp地址调用 OnIdle 虚函数实现空闲处理
当对话框销毁(必须利用DestroyWindow),消息循环才可退出。
推出前利用theApp地址调用 ExitInstance 虚函数实现退出前的善后处理工作。
模式对话框
#include <afxwin.h>
#include "resource1.h"
class CMyDlg : public CDialog
{
DECLARE_MESSAGE_MAP()
public:
CMyDlg() : CDialog(IDD_DIALOG1) {}
void OnCancel();
};
BEGIN_MESSAGE_MAP(CMyDlg, CDialog)
ON_COMMAND(IDCANCEL, OnCancel)
END_MESSAGE_MAP()
void CMyDlg::OnCancel()
{
this->DestroyWindow();
}
class CMyWinApp : public CWinApp
{
public:
virtual BOOL InitInstance();
};
BOOL CMyWinApp::InitInstance()
{
CMyDlg* pdlg = new CMyDlg;
this->m_pMainWnd = pdlg;
//pdlg->Create(IDD_DIALOG1);
//pdlg->ShowWindow(SW_SHOW);
//pdlg->UpdateWindow();
pdlg->DoModal();
return FALSE; // 不再执行MFC库中安排的Run函数
}
CMyWinApp theApp;
- 启动后进入入口函数 WinMain
- 获取应用程序类对象theApp的地址
- 利用theApp地址调用InitApplication,初始化当前应用程序的数据
- 利用theApp地址调用InitInstance函数,在函数中调用DoModal,DoModal 内部
- 将父窗口设置为不可用
- 创建无模式对话框
- 进入消息循环(自带的)
- 退出消息循环(父类的OnOK/OnCancel导致循环退出)
- 将父窗口设置为可用状态
- 销毁无模式对话框
- 不再执行CWinApp的Run函数进行消息循环
- 程序结束
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/278965.html