1.文件的查找
当对一个文件操作时,如果不知道该文件是否存在,就要首先进行查找。MFC中有一个专门用来进行文件查找的类CFileFind,使用它可以方便快捷地进行文件的查找。下面这段代码演示了这个类的最基本使用方法。
CString strFileTitle;
CFileFind finder;
BOOL bWorking = finder.FindFile("C://windows//sysbkup//*.cab");
while(bWorking)
{
bWorking=finder.FindNextFile();
strFileTitle=finder.GetFileTitle();
}
2.文件的打开/保存对话框
让用户选择文件进行打开和存储操作时,就要用到文件打开/保存对话框。MFC的类CFileDialog用于实现这种功能。使用CFileDialog声明一个对象时,第一个BOOL型参数用于指定文件的打开或保存,当为TRUE时将构造一个文件打开对话框,为FALSE时构造一个文件保存对话框。
在构造CFileDialog对象时,如果在参数中指定了OFN_ALLOWMULTISELECT风格,则在此对话框中可以进行多选操作。此时要重点注意为此CFileDialog对象的m_ofn.lpstrFile分配一块内存,用于存储多选操作所返回的所有文件路径名,如果不进行分配或分配的内存过小就会导致操作失败。下面这段程序演示了文件打开对话框的使用方法。
CFileDialog mFileDlg(TRUE,NULL,NULL,---
OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT|OFN_ALLOWMULTISELECT,
"All Files (*.*)|*.*||",AfxGetMainWnd());
CString str(" ",10000);
mFileDlg.m_ofn.lpstrFile=str.GetBuffer(10000);
str.ReleaseBuffer();
POSITION mPos=mFileDlg.GetStartPosition();
CString pathName(" ",128);
CFileStatus status;
while(mPos!=NULL)
{
pathName=mFileDlg.GetNextPathName(mPos);
CFile::GetStatus( pathName, status );
}
3.文件的读写
文件的读写非常重要,下面将重点进行介绍。文件读写的最普通的方法是直接使用CFile进行,如文件的创建打开读写可以使用下面的方法:
CFile创建和打开一个文件:
创建文件和打开文件的方法有很多种,下面简单介绍下几个构造函数:
CFile( LPCTSTR lpszFileName, UINT nOpenFlags );
throw( CFileException );
CFile( );
BOOL Open( LPCTSTR lpszFileName, UINT nOpenFlags, CFileException* pError = NULL );
lpszFileName:文件名称,可以是相对路径,绝对路径或网络路径
nOpenFlags:打开方式有:
·CFile::modeCreate 调用构造函数构造一个新文件,如果文件已存在,则长度变成0。
·CFile::modeNoTruncate 此值与modeCreate组合使用。如果所创建的文件已存在则其长度不变为0。因而此文件被打开,或者作为一个新文件或者作为一个已存在的文件。这将是很有用的,例如当打开一个可能存在也可能不存在的文件时。
·CFile::modeRead 打开文件仅供读。
·CFile::modeReadWrite 打开文件供读写。
·CFile::modeWrite 打开文件仅供写。
·CFile::modeNoInherit 阻止文件被子进程继承。
·CFile::ShareDenyNone 不禁止其它进程读或写访问,打开文件。如果文件已被其它进程以兼容模式打开,则Create失败。
·CFile::ShareDenyRead 打开文件,禁止其它进程读此文件。如果文件已被其它进程以兼容模式打开,或被其它进程读,则Create失败。
·CFile::ShareDenyWrite 打开文件,禁止其它进程写此文件。如果文件已被其它进程以兼容模式打开,或被其它进程写,则Create失败。
·CFile::ShareExclusive 以独占模式打开文件,禁止其它进程对文件的读写。如果文件已经以其它模式打开读写(即使被当前进程),则构造失败。
·CFile::ShareCompat 此标志在32位MFC中无效。此标志在使用CFile:: Open时映射为CFile::ShareExclusive。
·CFile::typeText 对回车换行设置特殊进程(仅用于派生类)。
·CFile::typeBinary 设置二进制模式(仅用于派生类)。
下面给出MSDN中的一个例子:
char* pFileName = "test.dat";
TRY
{
CFile f( pFileName, CFile::modeCreate | CFile::modeWrite );
}
CATCH( CFileException, e )
{
#ifdef _DEBUG
afxDump << "File could not be opened " << e->m_cause << "/n";
#endif
}
END_CATCH
CFile fileTest;
char* pFileName = "test.dat";
TRY
{
fileTest.Open(pFileName, CFile::modeCreate |CFile::modeWrite);
}
CATCH_ALL(e)
{
fileTest.Abort( );
THROW_LAST ( );
}
END_CATCH_ALL
//对文件进行读操作
//读取数据
UINT Read (void* lpBuf,UINT nCount);
throw(CFileException);// 返回值是传输到缓冲区的字节数。
//写入数据
void Write(const void* lpBuf,UINT nCount);
throw (CFileException);
char sRead[2];
CFile mFile(_T("user.txt"),CFile::modeRead);
if(mFile.GetLength()<2)
return;
mFile.Read(sRead,2);
mFile.Close();
//对文件进行写操作
CFile mFile(_T("user.txt "), CFile::modeWrite|CFile::modeCreate);
mFile.Write(sRead,2);
mFile.Flush();
mFile.Close();
虽然这种方法最为基本,但是它的使用繁琐,而且功能非常简单。我向你推荐的是使用CArchive,它的使用方法简单且功能十分强大。首先还是用CFile声明一个对象,然后用这个对象的指针做参数声明一个CArchive对象,你就可以非常方便地存储各种复杂的数据类型了。它的使用方法见下例。
//对文件进行写操作
CString strTemp="test";
CFile mFile;
mFile.Open("d://dd//try.TRY",CFile::modeCreate|CFile::modeNoTruncate|CFile::modeWrite);
CArchive ar(&mFile,CArchive::store);
ar<<strTemp;
ar.Close();
mFile.Close();
//对文件进行读操作
CFile mFile;
if(mFile.Open("d://dd//try.TRY",CFile::modeRead)==0)
return;
CArchive ar(&mFile,CArchive::load);
ar>>strTemp;
ar.Close();
mFile.Close();
CArchive的 << 和>> 操作符用于简单数据类型的读写,对于CObject派生类的对象的存取要使用ReadObject()和WriteObject()。使用CArchive的ReadClass()和WriteClass()还可以进行类的读写,如:
//存储CAboutDlg类
ar.WriteClass(RUNTIME_CLASS(CAboutDlg));
//读取CAboutDlg类
CRuntimeClass* mRunClass=ar.ReadClass();
//使用CAboutDlg类
CObject* pObject=mRunClass->CreateObject();
((CDialog* )pObject)->DoModal();
虽然VC提供的文档/视结构中的文档也可进行这些操作,但是不容易理解、使用和管理,因此虽然很多VC入门的书上花费大量篇幅讲述文档/视结构,但我建议你最好不要使用它的文档。关于如何进行文档/视的分离有很多书介绍,包括非常著名的《Visual C++ 技术内幕》。
如果你要进行的文件操作只是简单的读写整行的字符串,我建议你使用CStdioFile,用它来进行此类操作非常方便,如下例。
CStdioFile mFile;
CFileException mExcept;
mFile.Open( "d://temp//aa.bat", CFile::modeWrite, &mExcept);
CString string="I am a string.";
mFile.WriteString(string);
mFile.Close();
// 注:CStdioFile写入UNICODE字符时,必须指定文件类型为UNICODE,或者在文件头写入0XFFFE。
4.临时文件的使用
正规软件经常用到临时文件,你经常可以会看到C:/Windows/Temp目录下有大量的扩展名为tmp的文件,这些就是程序运行是建立的临时文件。临时文件的使用方法基本与常规文件一样,只是文件名应该调用函数GetTempFileName()获得。它的第一个参数是建立此临时文件的路径,第二个参数是建立临时文件名的前缀,第四个参数用于得到建立的临时文件名。得到此临时文件名以后,你就可以用它来建立并操作文件了,如:
char szTempPath[_MAX_PATH],szTempfile[_MAX_PATH];
GetTempPath(_MAX_PATH, szTempPath);
GetTempFileName(szTempPath,_T ("my_"),0,szTempfile);
CFile m_tempFile(szTempfile,CFile:: modeCreate|CFile:: modeWrite);
char m_char='a';
m_tempFile.Write(&m_char,2);
m_tempFile.Close();
5.获取文件名,文件类型,文件长度,文件路径
用利用CFile打开一个文件时,可以在利用成员函数
virtual CString GetFileName( ) const,
virtual CString GetFileTitle( ) const,
virtual CString GetFilePath( ) const,
virtual DWORD GetLength( ) const;throw( CFileException );
来取得相关信息,如果一个文件的全路经是: c:/windows/write/myfile.wri,则每个函数取得的是: myfile.wri, myfile, c:/windows/write/myfile.wri. GetLength取得文件大小是按字节为单位的。
也可以利用:
virtual void SetLength( DWORD dwNewLen );throw( CFileException );
virtual void SetFilePath( LPCTSTR lpszNewName );
来设置文件的长度和路径。
在当前的文件下面新建一个Text.txt文件,在里面写点东西,然后运行下面程序:
CFile file("Text.txt",CFile::modeReadWrite);
ULONGLONG length;
CString strFilePath;
length = file.GetLength();
length = length + 1024*10;
file.SetLength(length);
file.SetFilePath("D://Text.txt");
strFilePath = file.GetFilePath();
MessageBox(strFilePath);
file.Close();
最后发现文件的路径变了,但是在D盘下面并没有找到Text.txt,原因是SetFilePath只能指定一个路径给文件,SetFilePath并不能做为移动文件来使用。
CFile并没有给出取得文件类型的函数,但可以利用API来实现。
5.文件的复制、删除等
MFC中没有提供直接进行这些操作的功能,因而要使用SDK。SDK中的文件相关函数常用的有CopyFile()、CreateDirectory()、DeleteFile()、MoveFile()。它们的用法很简单,可参考MSDN。