MFC数据的保存和打开

MFC中数据的保存和打开有三种处理方式:

第一种:CFileDialog + CFile数据结构体
使用传统的File类,通过这个类的Open、write、read等函数对要保存的数据进行保存。但是使用这种方式保存,就需要将要保存的数据定制成一个结构体,以结构体的对象对数据进行保存。使用这种方式存储数据,有可能会造成数据存储控件的浪费,并且操作不方便。

第二种:CFileDialog + CFile+ CArchive:
使用CArchive这个类,CArchive类对CFile类再封装之后不再使用结构体作为储存单元,把每条信息的的各个字段按照固定顺序存取即可,并且字符串都是按照实际长度进行储存de存储的结构也非常紧凑。CArchive类其中大量重载了“operator<< ”和“opertor >>”函数,使用各种类型数据的文件存储更加方便;CArchive类的输出输入功能,仿制了标准的C++的fstrean类的输入输出符号被CDocument类引用后就巧妙的搭建起序列化高级存储结构。

第三种:CFileDialog + CDocument:
使用CDocument类的序列化存储结构那是的数据的存取操作非常的方便。只要调用OnOpenDocument或者OnSaveDocument函数CDocument类内部就会自动构建好CArchive对象,在Serialize虚函数中提供开发者带入的存取数据。CDocument类实现序列化存储的核心是Serialize函数,他既负责用户数据保存也负责数据的加载。、Serialize函数通过参数(CArchive::IsStoring)判断任务性质如果是正在执行保存任务,则调用输出符号,将用户输入的数据保存到文件中,否则调用输入符号将文件中存储的数据提取到应用程序中。

以上这三种方式都可对数据进行存储,每一种方式都是有上一种方式的封装和继承。在以上三种方式中CFileDialog类是打开一个文件选择窗口,选择文件的保存/打开的文件名称和位置。

下面就是对这几种存储方式的使用实例:

第一种:CFileDialog + CFile+数据结构体

  • 1、创建数据存储结构体
struct SDate 
{
	int nub;
	char name[40];
	COleDateTime join;
};
  • 2、使用CFileDialog+CFile进行存储数据
void CDocumentDlg::OnSave() 
{
	LPCSTR szFilter = "信息文件(*.fff)|*.ff|所有文件|(*.*)|*.*||"; //设置文件过滤器
	CFileDialog fileDlg(false,"*.ff",NULL,OFN_OVERWRITEPROMPT,szFilter); //设置文件打开/保存的弹出框
	if(IDCANCEL == fileDlg.DoModal())
		return;
	CString szfile = fileDlg.GetPathName();
	CFile file;
	if (!file.Open(szfile,CFile::modeCreate|CFile::modeWrite))
	{
		AfxMessageBox("保存数据失败!");
		return;
	}
	int i = 0,ncount = m_list.GetItemCount();
	SDate date;
	while(i<ncount)
	{
		date.nub = atoi(m_list.GetItemText(i,0));
		CString time = m_list.GetItemText(i,2);
	    m_list.GetItemText(i,1,date.name,sizeof(date.name));
		date.join.ParseDateTime(m_list.GetItemText(i,2));
		file.Write(&date,sizeof(date));//将结构体中数据存储到文档中。
		i++;
	}
	
}
  • 3、使用CFileDialog+CFile进行打开数据
void CDocumentDlg::OnOpen() 
{
	LPCSTR szFilter = "信息文件(*.fff)|*.ff|所有文件|(*.*)|*.*||"; //设置文件过滤器
	CFileDialog  fileDlg(TRUE,"*.ff",NULL,OFN_OVERWRITEPROMPT,szFilter); //设置文件打开/保存的弹出框
	if(IDCANCEL == fileDlg.DoModal())
		return;
	CString szfile = fileDlg.GetPathName();
	CFile file;
	if (!file.Open(szfile,CFile::modeRead|CFile::shareDenyNone))//打开文件
	{
		AfxMessageBox("保存数据失败!");
		return;
	}
	m_list.DeleteAllItems();
	int i = 0;
	SDate date;
	CString str;
	while(file.Read(&date,sizeof(date)) == sizeof(date))//将文档中的数据读取到结构体中
	{
		str.Format("%d",date.nub);
		m_list.InsertItem(i,str);
		m_list.SetItemText(i,1,date.name);
		m_list.SetItemText(i,2,date.join.Format("%Y-%m-%d"));
		i++;
	}
}

第二种:CFileDialog + CFile+ CArchive

  • 1、使用CFileDialog + CFile+ CArchive进行数据的保存
void CMainView::OnFileSaveAs() 
{
	LPCSTR szFilter = "信息文件(*.fff)|*.fff|所有文件|(*.*)|*.*||"; //设置文件过滤器
	CFileDialog fileDlg(false,"*.ff",NULL,OFN_OVERWRITEPROMPT,szFilter); //设置文件打开/保存的弹出框
	if(IDCANCEL == fileDlg.DoModal())
		return;
	CString szfile = fileDlg.GetPathName();
	m_path = szfile;
	CFile file;
	if (!file.Open(szfile,CFile::modeCreate|CFile::modeWrite))//通过CFileDialog 选择打开的位置,打开要保存的文件
	{
		AfxMessageBox("保存数据失败!");
		return;
	}
	CArchive chive(&file,CArchive::store);//CFile对象是永久数据的最终的源或目标。 
	int i = 0,ncount = m_list.GetItemCount();
	chive << ncount; //使用<<将数据存入到文档
	COleDateTime time;
	while(i<ncount)
	{
		chive << m_list.GetItemText(i,0);//使用<<将数据存入到文档
		chive << m_list.GetItemText(i,1);//使用<<将数据存入到文档
		chive << m_list.GetItemText(i,2);;//使用<<将数据存入到文档
		i++;
	}
}
  • 2、使用CFileDialog + CFile+ CArchive进行数据的打开
void CMainView::OnOpen() 
{
	if (m_bModify)
	{
		Chick();
	}	
	LPCSTR szFilter = "信息文件(*.fff)|*.fff|所有文件|(*.*)|*.*||"; //设置文件过滤器
	CFileDialog fileDlg(TRUE,"*.ff",NULL,OFN_OVERWRITEPROMPT,szFilter); //设置文件打开/保存的弹出框
	if(IDCANCEL == fileDlg.DoModal())
		return;
	m_path = fileDlg.GetPathName();
	CFile file;
	if (!file.Open(m_path,CFile::modeRead|CFile::shareDenyNone))
	{
		AfxMessageBox("保存数据失败!");
		return;
	}
	CArchive chive(&file,CArchive::load);
	COleDateTime time;
	m_list.DeleteAllItems();
	int i = 0,nnub = 0,ncount = 0;
	CString str;
	chive >> ncount;
	while(i<ncount)
	{
		chive >> str;
		m_list.InsertItem(i,str);
		chive >> str;
		m_list.SetItemText(i,1,str);
		chive >> str;
		m_list.SetItemText(i,2,str);
		i++;	
	}
	m_bModify = TRUE;
}

第三种:CFileDialog + CDocument:
这种方式比较复杂一些,需要在MFC选择文档视图结构的时候使用。

  • 1、使用CFileDialog + CDocument:对数据进行保存

1)、当有保存信号之后,会使用CDocument对象调用OnSaveDocument函数进行存储。

void CMainView::OnSave() 
{
	if (m_path.IsEmpty())
	{
		LPCSTR szFilter = "信息文件(*.fff)|*.fff|所有文件|(*.*)|*.*||"; //设置文件过滤器
		CFileDialog fileDlg(false,"*.ff",NULL,OFN_OVERWRITEPROMPT,szFilter); //设置文件打开/保存的弹出框
		if(IDCANCEL == fileDlg.DoModal())
			return;
		CString szfile = fileDlg.GetPathName();
		m_doc.OnSaveDocument(szfile);//调用CDocument类中的OnSaveDocument函数进行数据存储
return;
		}
	m_doc.OnSaveDocument(m_path);	

}

2)、打开文件,同样打开文件的时候也是有CDocument类调用函数OnOpenDocument,在这个函数中同样最后要调用CDocument中的Serialize这个函数。只不过在调用的时候CDocument有一个变量ar.IsStoring(),如果这个变量为True的话则是存储,为FALSE的话则是打开。

void CMainView::OnOpen() 
{
	if (m_doc.IsModified())
	{
		Chick();
	}	
	LPCSTR szFilter = "信息文件(*.fff)|*.fff|所有文件|(*.*)|*.*||"; //设置文件过滤器
	CFileDialog fileDlg(TRUE,"*.ff",NULL,OFN_OVERWRITEPROMPT,szFilter); //设置文件打开/保存的弹出框
	if(IDCANCEL == fileDlg.DoModal())
		return;
	m_path = fileDlg.GetPathName();
	m_doc.OnOpenDocument(m_path);
}
  • 2、调用CDocument类中的OnSaveDocument函数进行数据存储的时候,CDocument类会调用派生类中的Serialize函数,实际进行数据的存储。
void CSDIDoc::Serialize(CArchive& ar)
{
	POSITION pos = GetFirstViewPosition();
	while (pos)
	{
		CView* pView = GetNextView(pos);
		pView->Serialize(ar);
   }  

}
  • 3、CView类中自定义的的Serialize函数,实际上存储的算法都在这个函数中
void CMainView::Serialize(CArchive &ar)
{
	if (ar.IsStoring()) 
	{
		int i = 0,ncount = m_list.GetItemCount();
		ar << ncount;
		while(i<ncount)
		{
			ar << m_list.GetItemText(i,0);
			ar << m_list.GetItemText(i,1);
			ar << m_list.GetItemText(i,2);;
			i++;
		}
		AfxMessageBox("保存成功");
 	}
	else
	{
		m_list.DeleteAllItems();
		int i = 0,nnub = 0,ncount = 0;
		CString str;
		ar >> ncount;
		while(i<ncount)
		 {
			ar >> str;
			m_list.InsertItem(i,str);
			ar >> str;
		 	m_list.SetItemText(i,1,str);
		 	ar >> str;
			m_list.SetItemText(i,2,str);
		 	i++;	
		}
		m_doc.SetModifiedFlag(TRUE);
	}
}

你可能感兴趣的:(MFC笔记,mfc)