友情提示:如果本网页打开太慢或显示不完整,请尝试鼠标右键“刷新”本网页!
深入浅出MFC第2版(PDF格式)-第92部分
快捷操作: 按键盘上方向键 ← 或 → 可快速上下翻页 按键盘上的 Enter 键可回到本书目录页 按键盘上方向键 ↑ 可回到本页顶部! 如果本书没有阅读完,想下次继续接着阅读,可使用上方 "收藏到我的浏览器" 功能 和 "加入书签" 功能!
shareExclusive = 0x0010; // 唯我使用
shareDenyWrite = 0x0020;
shareDenyRead =0x0030;
shareDenyNone =0x0040;
modeNoInherit =0x0080;
modeCreate = 0x1000; //产生新档(甚至即使已有相同名称之文件存在)
modeNoTruncate = 0x2000;
typeText = 0x4000; // typeText and typeBinary are used in
typeBinary = (int)0x8000 // derived classes only
};
typeText = 0x4000; // typeText and typeBinary are used in
typeBinary = (int)0x8000 // derived classes only
};
499
…………………………………………………………Page 562……………………………………………………………
第篇 深入 MFC 程式設計
再举一例,下面这段程序代码可将文件mydoc。doc 的所有文字转换为小写:
char* pBuffer = new char'0x1000';
CFile file(〃mydoc。doc〃; CFile::modeReadWrite);
DWORD dwBytesRemaining = file。GetLength();
UINT nBytesRead;
DWORD dwPosition;
while (dwBytesRemaining) {
dwPosition = file。GetPosition();
nBytesRead = file。Read(pBuffer; 0x1000);
::CharLowerBuff(pBuffer; nBytesRead);
file。Seek((LONG)dwPosition; CFile::begin);
file。Write(pBuffer; nBytesRead);
dwBytesRemaining …= nBytesRead;
}
delete'' pBuffer;
文件的操作常需配合对异常情况(exception )的处理,因为文件的异常情况特别多:档
案找不到啦、文件handles 不足啦、读写失败啦。。。。上一例加入异样情况处理后如下:
char* pBuffer = new char'0x1000';
try {
CFile file(〃mydoc。doc〃; CFile::modeReadWrite);
DWORD dwBytesRemaining = file。GetLength();
UINT nBytesRead;
DWORD dwPosition;
while (dwBytesRemaining) {
dwPosition = file。GetPosition();
nBytesRead = file。Read(pBuffer; 0x1000);
::CharLowerBuff(pBuffer; nBytesRead);
file。Seek((LONG)dwPosition; CFile::begin);
file。Write(pBuffer; nBytesRead);
dwBytesRemaining …= nBytesRead;
}
}
catch (CFileException* e) {
if (e…》cause == CFileException::fileNoteFound)
MessageBox(〃File not found〃);
else if (e…》cause == CFileException::tooManyOpeFiles)
MessageBox(〃File handles not enough〃);
else if (e…》cause == CFileException::hardIO)
500
…………………………………………………………Page 563……………………………………………………………
第8章 Document…View 深入探討
MessageBox(〃Hardware error〃);
else if (e…》cause == CFileException::diskFull)
MessageBox(〃Disk full〃);
else if (e…》cause == CFileException::badPath)
MessageBox(〃All or part of the path is invalid〃);
else
MessageBox(〃Unknown file error〃);
e…》Delete();
}
delete'' pByffer;
台面上的Serialize 动作
让我以Scribble 为例,向你解释台面上的(应用程序代码中可见的)serialization 动作。根
据图8…3 的数据结构,Scribble 程序的文件读写动作是这么分工的:
Framework 调用CSribbleDoc::Serialize,用以对付文件。
CScribbleDoc 再往下调用CStroke::Serialize,用以对付线条。
CStroke 再往下调用CArray::Serialize,用以对付点数组。
读也由它,写也由它,究竟Serialize 是读还是写?这一点不必我们操心。Framework 呼
Serialize 时会传来一个CArchive 对象(稍后我会解释CArchive),你可以想象它
代表一个文件,透过其IsStoring 成员函数,即可知道究竟要读还是写。图8…5 是各层
叫
级的Serialize 动作示意图,文字说明已在图片之中。
注意:Scribble 程序使用CArray 储存鼠标位置坐标,而CArray 是
一个template class ,解释起来比较复杂。所以稍后我挖给各位看的Serialize 函数原始
码,采用CDWordArray 的成员函数而非CArray 的成员函数。Visual C++ 1。5 版的
Scribble 范例程序就是使用CDWordArray (彼时还未有template class )。
然而,为求完备,我还是在此先把CArray 的Serialize 函数源代码列出:
template
void AFXAPI SerializeElements (CArchive& ar; TYPE* pElements; int nCount)
{
ASSERT(nCount == 0 ||
501
…………………………………………………………Page 564……………………………………………………………
第篇 深入 MFC 程式設計
AfxIsValidAddress(pElements; nCount * sizeof(TYPE)));
// default is bit…wise read/write
if (ar。IsStoring())
ar。Write ((void*)pElements; nCount * sizeof(TYPE));
else
ar。Read ((void*)pElements; nCount * sizeof(TYPE));
}
template
void CArray::Serialize(CArchive& ar)
{
ASSERT_VALID(this);
CObject::Serialize(ar);
if (ar。IsStoring())
{
ar。WriteCount (m_nSize);
}
else
{
DWORD nOldSize = ar。ReadCount ();
SetSize (nOldSize; …1);
}
SerializeElements (ar; m_pData; m_nSize);
}
void CScribbleDoc::Serialize(CArchive& ar)
2 CObList::Serialize(Carchive& ar)
{ { 。。。 } //源代码请看图8…5b
if (ar。IsStoring())
{ }
m_strokeList 是
else
{ } CObList 对象
1
m_strokeList。Serialize(ar);
}
//………………………………………………………………………………………………………… 到 的过程并非显而易见,
void CStroke::Serialize(CArchive& ar) 3 下一节将有详细说明。
{
if (ar。IsStoring()) {
ar 》 w; 5 CDWordArray::Serialize(Carchive& ar)
m_nPenWidth = w; { 。。。 } //源代码请看图8…5c
m_pointArray。Serialize(ar);
}
}
图8…5a Scribble Step1 的文件读写 (档)动作
502
…………………………………………………………Page 565……………………………………………………………
第8章 Document…View 深入探討
void CObList::Serialize(CArchive& ar)
{
ASSERT_VALID(this);
CObject::Serialize(ar);
if (ar。IsStoring())
{
ar。WriteCount(m_nCount);
for (CNode* pNode = m_pNodeHead; pNode != NULL;
pNode = pNode…》pNext)
{ // J。J。Hou :针对串行中的每一个元素写文件
ASSERT(AfxIsValidAddress(pNode; sizeof(CNode)));
ar data;
}
这将引发CArchive 的多载
}
else else 运算子,稍后有深入说明。
{
DWORD nNewCount = ar。ReadCount();
CObject* newData;
while (nNewCount……)
{ //
J。J。Hou : 一一读入文件内容,加入串行
ar 》》 newData;
AddTail(newData);
}
}
}
图8…5b CObList::Serialize 源代码
void CDWordArray::Serialize(CArchive& ar)
{
ASSERT_VALID(this);
CObject::Serialize(ar);
if (ar。IsStoring())
{
ar。WriteCount(m_nSize); //
把数组大小(元素个数)写入ar
ar。Write(m_pData; m_nSize * sizeof(DWORD)); //把整个数组写入ar
}
else
{
DWORD nOldSize = ar。ReadCount();
SetSize(nOldSize); // 从 ar 中读出数组大小(元素个数)
ar。Read(m_pData; m_nSize * sizeof(DWORD)); // ar ar ar
从 中读出整个数组
}
}
图8…5c CDWordArray::Serialize 源代码
503
…………………………………………………………Page 566……………………………………………………………
第篇 深入 MFC 程式設計
File/Save
【 】
CScribbleDoc 要求线条串
快捷操作: 按键盘上方向键 ← 或 → 可快速上下翻页 按键盘上的 Enter 键可回到本书目录页 按键盘上方向键 ↑ 可回到本页顶部!
温馨提示: 温看小说的同时发表评论,说出自己的看法和其它小伙伴们分享也不错哦!发表书评还可以获得积分和经验奖励,认真写原创书评 被采纳为精评可以获得大量金币、积分和经验奖励哦!