对于文档,MFC默认做法是二进制序列化(即重写文档类的Serialize()函数,用XXXXXStoring()判断是打开还是保存),大部分教材上也是这么教的。
但是我们常常需要使用其它格式保存文档(比如XML格式、BMP格式等),而这时文档已被打开,序列化时常会破坏原来的数据格式,导致文件损坏。所以大部分情况下,序列化并没有什么用处,反而会有坏处,我们通常不需要使用序列化。
不使用序列化的方法很简单,重写OnOpenDocument()和OnSaveDocument函数(它们默认打开文件,构建CArchive并调用Serialize函数),用自己的打开、保存代码重写之后,就不会自动打开文件并序列化了,可以安全地使用其它格式。
比如我的
XML Tree分析器的打开和保存代码,可以这样写——
<code class="lang-cpp">void CXmlTree01Doc::Serialize(CArchive& ar)
{
// 不使用序列化 —— 打开和保存代码见OnOpenDocument和OnSaveDocument
if (ar.IsStoring())
{
}
else
{
}
}
BOOL CXmlTree01Doc::OnSaveDocument(LPCTSTR lpszPathName)
{
return FALSE; // 保存失败!
}
BOOL CXmlTree01Doc::OnOpenDocument(LPCTSTR lpszPathName)
{
if (!CDocument::OnOpenDocument(lpszPathName))
return FALSE;
MSXML2::IXMLDOMDocumentPtr pDoc; // 文档对象
MSXML2::IXMLDOMElementPtr xmlRoot; // 根元素
HRESULT hr = pDoc.CreateInstance(_uuidof(MSXML2::DOMDocument30)); // 使用的msxml版本和新建对象的版本必须一致
if (FAILED(hr))
{
AfxMessageBox("无法创建DOM文件对象,检查是否安装MS XML Parser运行库!");
return FALSE;
}
pDoc->load(lpszPathName);
MSXML2::IXMLDOMElementPtr pElement;
pElement = pDoc->GetdocumentElement();
m_rootnode.name = (char *)pElement->GettagName();
m_rootnode.child = NULL;
m_rootnode.sibling = NULL;
m_rootnode.text = (char*)pElement->Gettext();
ReadAttribute(pElement, &m_rootnode);
ReadElements(pElement->GetfirstChild(), &m_rootnode);
this->SetModifiedFlag(false);
return TRUE;
}</code>
原来的不科学代码——
<code class="lang-cpp">void CXmlTree01Doc::Serialize(CArchive& ar)
{
MSXML2::IXMLDOMDocumentPtr pDoc; // 文档对象
MSXML2::IXMLDOMElementPtr xmlRoot; // 根元素
HRESULT hr = pDoc.CreateInstance(_uuidof(MSXML2::DOMDocument30)); // 使用的msxml版本和新建对象的版本必须一致
if (FAILED(hr))
{
AfxMessageBox("无法创建DOM文件对象,检查是否安装MS XML Parser运行库!");
return;
}
if (ar.IsStoring())
{
// TODO: 在此添加存储代码
ASSERT(!"不支持程序保存!");
}
else
{
// TODO: 在此添加加载代码
CFile *f = ar.GetFile();
if (f == NULL) return;
pDoc->load((const char*)f->GetFilePath());
MSXML2::IXMLDOMElementPtr pElement;
pElement = pDoc->GetdocumentElement();
m_rootnode.name = (char *)pElement->GettagName();
m_rootnode.child = NULL;
m_rootnode.sibling = NULL;
m_rootnode.text = (char*)pElement->Gettext();
ReadAttribute(pElement, &m_rootnode);
ReadElements(pElement->GetfirstChild(), &m_rootnode);
this->SetModifiedFlag(false);
}
}</code>
XmlTree01-改进版.rar
407.81KB
RAR
18次下载