MFC中文件的建立
在操作系统中,文件是放在一定的目录下,在创建以及操作文件以前,我们要查看文件要保存的目录有没有存在,如果不存在要创建。这就要用到GetFileAttributes()和CreateDirectory()两个函数。下面是这两个函数的简介:
1、GetFileAttributes
函数原型:
DWORD WINAPI GetFileAttributes( __in LPCTSTR lpFileName );
函数参数
lpFileName [in] :文件或目录的名字,对于ANSI版本,名字不能大于MAX_PATH。
函数返回值
如果函数成功,返回值包含文件或目录的属性。如果函数失败,返回值是INVALID_FILE_ATTRIBUTES。
在MSDN中,文件总共有15种属性,根据磁盘的分区格式不同,文件的属性也会不同。现在针对GetFileAttributes 函数的返回值做以下整理:
返回字段
返回值
属性类型
FILE_ATTRIBUTE_READONLY
1
只读
FILE_ATTRIBUTE_HIDDEN
2
隐藏
FILE_ATTRIBUTE_SYSTEM
4
系统
FILE_ATTRIBUTE_DIRECTORY
16
目录
FILE_ATTRIBUTE_ARCHIVE
32
存档
FILE_ATTRIBUTE_DEVICE
64
保留
FILE_ATTRIBUTE_NORMAL
128
正常
FILE_ATTRIBUTE_TEMPORARY
256
临时
FILE_ATTRIBUTE_SPARSE_FILE
512
稀疏文件
FILE_ATTRIBUTE_REPARSE_POINT
1024
超链接或快捷方式
FILE_ATTRIBUTE_COMPRESSED
2048
压缩
FILE_ATTRIBUTE_OFFLINE
4096
脱机
FILE_ATTRIBUTE_NOT_CONTENT_INDEXED
8192
索引
FILE_ATTRIBUTE_ENCRYPTED
16384
加密
FILE_ATTRIBUTE_VIRTUAL
65536
虚拟
橙色标记的属性为Windows系统中文件的公有属性,其中“只读”、“隐藏”、“系统”、“存档”为文件的四种基本属性。compressed,content_indexed,encrypted只存在于NTFS分区中。
文件去掉全部属性后(四种基本属性),将自动标记为normal。同时具有system和hidden属性的文件会在系统中彻底隐形,这也是病毒常用的伎俩。
commpressed和encrypted不能共存。默认情况下文件都有content_indexed属性
以上内容转自:http://hi.baidu.com/li0544/item/5c6a4f0872c7ac18ebfe3856
2、CreateDirectory
函数原型
BOOL CreateDirectory(LPCTSTR lpPathName, LPSECURITY_ATTRIBUTES lpSecurityAttributes );
第一个参数值为文件夹名称,第二个参数值为安全属性,一般设置为NULL即可。如果正确创建,返回值为1,如果没有正常创建文件夹,则返回0。
特别的:该函数每次调用时都只能创建一级文件夹,即文件夹中不能再包含子文件夹。
当希望创建含有子文件夹的文件夹时,可以先使用该函数创建一级文件夹,然后再使用该函数在一级文件夹下创建子文件夹。如:
希望创建:d:\\TEST\\temp,
则:CString str = “d:\\TEST”;
CreateDirectory(str, NULL);
str = str + \\temp;
CreateDirectory(str, NULL);
综合利用以上两个函数的例子如下:
if (!(GetFileAttributes("DataBase")==FILE_ATTRIBUTE_DIRECTORY))
{
if (!CreateDirectory("DataBase",NULL))
{
AfxMessageBox("Make Dir Error");
}
}
接下来我们就要直接编写文件并且直接对文件进行打开、关闭、读、写等操作。MFC把这些对文件的操作封装到了一个叫做CFile的类中,使用这个类的对象能够以更直接的方式来处理文件。
CFile是MFC文件类的基类,它直接提供非缓冲的二进制磁盘输入/输出设备,并直接地通过派生类支持文本文件和内存文件。
使用CFILE类必须包含 #include <afx.h>
通常,CFILE类的构造过程中会自动打开磁盘文件,在析构函数中则会自动关闭文件。你可以使用静态成员函数来询问文件的状态而不用打开文件。
在MFC里面,打开一个文件最常用的方法分为以下两步:
1.创建一个用于打开文件的对象,通常都是声明一个CFile或者一个CFile派生类的对象。
2.调用该CFile对象的Open方法,并提供一个文件路径和打开方式作为Open方法的参数。
下面就Cfile类封装的函数进行介绍
1、CFile::Open
Open函数的原型如下:
virtual BOOL Open( LPCTSTR lpszFileName, UINT nOpenFlags, CFileException* pError = NULL );
返回值:成功为非0,否则为0,仅当返回值为0时pError参数才有意义
参数:
lpszFileName 需要打开文件的路径字符串,这个路径可以是相对路径也可以是绝对路径,或者是网络名字(UNC)
nOpenFlags 一个UINT定义文件的存取共享模式。它指定文件打开时可以采取的操作。你可以使用”|"号来组合多个选项。文件的一个存取权限和一个共享选项是必须要指定的。而modeCreate 和modeNoInherit是可选的。
具体如下:
CFile::modeCreate 让构造器创建一个新文件,如果那个文件已经存在,把那个文件的长度重设为
CFile::modeNoTruncate 可以同modeCreate. 一起用,如果要创建的文件已经存在,并不把它长度设置为0,因而这个文件获取或者作为一个新建文件或者作为一个已存在文件打开。这个功能往往很好用,比如说,当你需要打开一个设置文件,但是你并不清楚这个文件是否已经存在。
CFile::modeRead 打开文件仅仅供读
CFile::modeReadWrite 打开文件供读写
CFile::modeWrite 打开文件只供写
CFile::modeNoInherit 阻止这个文件被子进程继承
CFile::shareDenyNone 打开这个文件同时允许其它进程读写这个文件。如果文件被其它进程以incompatibility模式打开,这是create操作会失败。
CFile::shareDenyRead 打开文件拒绝其它任何进程读这个文件。如果文件被其它进程用compatibility模式或者是读方式打开,create操作失败。
CFile::shareDenyWrite 打开文件拒绝其它任何进程写这个文件。如果文件被其它进程用compatibility模式或者是写方式打开,create操作失败。
CFile::shareExclusive 以独占方式打开这个文件,不允许其它进程读写这个文件。 Construction fails if the file has been opened in any other mode for read or write access, even by the current process.
CFile::shareCompat 这个标志在32位的MFC中无效。 This flag maps to CFile::shareExclusive when used in CFile::Open.
CFile::typeText 设置成对回车换行对有特殊处理的文本模式(仅用在派生类中)
CFile::typeBinary 设置二进制模式(仅用在派生类中)
pError-------一个指向一个已经存在的file-exception类的指针,它会接收文件失败操作的具体状态。
注明:
OPEN默认是用在CFILE的构造器中,这两个函数提供了一个对文件的安全访问方式,即使发生了错误也会正确的回报错误。
以上内容转自http://blog.sina.com.cn/s/blog_673209640100i6pi.html
// example for CFile::Open
CFile f;
CFileException e;
char* pFileName = "test.dat";
if(!f.Open(pFileName, CFile::modeCreate | CFile::modeWrite,&e))
{
#ifdef _DEBUG
afxDump<<"File could not be opened"<<e.m_cause<<"\n";
#endif
}
注:CFileException类:
一个CFileException对象代表了与文件相关的异常。CFileException类包括有可移植的原因代码和操作系统指定错误值等公共数据成员。此类也提供产生文件异常的静态成员函数,返回操作系统和C运行中的错误原因代码。
CFileException对象在CFile成员函数中被创建和产生,也可在派生类成员函数中创建或产生。可在CATCH表达式范围内访问这些对象。因为可移植,可以仅用出错代码获取异常的原因。
#include <afx.h>
CFileException类的成员
数据成员
m_cause | 包含异常原因相对应的可移植代码 |
m_IosError | 包含相关操作系统错误代码 |
m_strFileName | 包含异常的文件名 |
构造函数
构造一个CFileException对象 |
代码转换
OsErrorToException | 返回与操作系统错误值相对应的出错原因代码 |
ErrnoToException | 返回与运行错误值相对应的出错原因代码 |
帮助函数
ThrowOsError | 返回一个基于操作系统错误值相对应的出错原因代码 |
ThrowErrno | 产生一个基于运行错误值的文件异常 |
2、CFile::Read
函数原型
virtual UINT Read (void* lpBuf,UINT nCount);
返回值:
传输到缓冲区的字节数。注意对所有CFile类,如果到达文件尾,则返回值可能比nCount小。
参数: lpBuf 指向用户提供的缓冲区以接收从文件中读取的数据。 nCount 可以从文件中读出的字节数的最大值。对文本模式的文件,回车换行作为一个字符。
说明:从与CFile对象相关联的文件读数据到缓冲区。
示例:
// example for CFile::Read
extern CFile cfile;
char pbuf[100];
UINT nBytesRead = cfile.Read(pbuf,100);
3、CFile::Write
函数原型
virtual void Write(const void* lpBuf,UINT nCount);
throw (CFileException);
参数: lpBuf 指向用户提供的缓冲区,包含将写入文件中的数据。 nCount 从缓冲区内传输的字节数。对文本模式的文件,回车换行作为一个字符。
说明:
将数据从缓冲区写入与CFile对象相关联的文件
示例:// example for CFile::Write
extern CFile cfile;
char pbuf[100];
cfile.Write(pbuf,100);
4、CFile::Seek
在打开的文件中重新定位一个指针。
函数原型
virtual LONG Seek(LONG lOff,UINT nFrom);
throw(CFileException);
返回值:如果要求的位置合法,则Seek返回从文件开始起的新字节偏移量。否则值未定义并产生CFileException异常。
参数: lOff 指针移动的字节数。 nFrom 指针移动的模式,可为以下值之一:
CFile::begin 从文件开始,把指针向后移动lOff字节。
CFile::current 从当前位置开始,把指针向后移动lOff字节。
CFile::end 从文件尾开始,把指针向前移动lOff字节。注意必须移动到存在的文件中,因而lOff应为负。如果为正值,则超出文件尾。
示例:
// example for CFile::Seek
extern CFile cfile;
LONG lOffset = 1000;
LONG lActual = cfile.Seek(lOffset, CFile::begin);
5、CFile::SeekToBegin
函数原型:
void SeekToBegin( );
说明:
将文件指针指向文件开始处,等价于Seek(0L, CFile::begin)
示例:// example for CFile::SeekToBegin
extern CFile cfile;
cfile.SeekToBegin( );
6、CFile::SeekToEnd
函数原型:
DWORD SeekToEnd( );
返回值:文件长度(字节数)。
说明:
将文件指针指向文件逻辑尾部,等价于CFile::Seek( 0L, CFile::End);
示例:// example for CFile::SeekToEnd
extern CFile cfile;
DWORD dwActual = cfile.SeekToEnd( );
6、CFileFind类
CFileFind( );//构造函数。
virtual BOOL FindFile(LPCTSTR pstrName = NULL, DWORD dwUnused = 0);
参数: pstrName 指向待找文件名字符串,如果为NULL,则查找以*.*形式进行。
dwUnused 保留,以使FindFile在派生类多形,必须为0。
n virtual BOOL FindNextFile( );
返回值:如果还有文件,则返回非零值;如果为最后一个文件,则为0。
以下代码将当前目录下的文件枚举出来并打印每个文件名:CFileFind finder
BOOL bWorking = finder.FindFile("*.*");
while(bWorking)
{
bWorking = finder.FindNextFile( );
cout <<(LPCTSTR) finder.GetFileName( ) <<endl;
}