按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
关文件、读文件、写文件、搜寻资料。。。。MFC 把这些操作都包装在CFile 之中。可想而知,它
必然有Open、Close、Read 、Write、Seek 。。。 等等成员函数。下面这段程序代码示范CFile 如
何读档:
char* pBuffer = new char'0x8000';
CFile file(〃mydoc。doc〃; CFile::modeRead); //
打开mydoc。doc 文件,使用只读模式。
UINT nBytesRead = file。Read(pBuffer; 0x8000); // 读取8000h 个字节到pBuffer 中。
上述程序片段中,对象file 的构造式将打开mydoc。doc 档。并且由于此对象产生于函数
的堆栈之中,当函数结束,file 的析构式将自动关闭mydoc。doc 档。
开文件模式有许多种,都定义在CFile (AFX。H )之中:
enum OpenFlags {
modeRead = 0x0000; //只读
modeWrite = 0x0001; // 唯写
modeReadWrite =0x0002; // 可读可写
sharepat = 0x0000;
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