第 6章 文件操作内容摘要:
1,使用 CFile类进行文件读写,删除,改名及访问文件属性
2,使用 CStdioFile类操作文本文件
3,使用 CFileFind类查找文件
4.了解 windows API的文件操作返回目录
6.1 文件操作类 CFile
学习目标使用 CFile类进行文件读写、删除、改名及访问文件属性,
6.1
返回第 6章
( 1) 文件打开函数 Open
BOOL Open( LPCTSTR lpszFileName,UINT nOpenFlags,CFileException* pError = NULL) ;
参数 lpszFileName,为欲打开的文件名,文件名可以包含路径和文件名两部分 。
如,d:\\bak\\test.txt”,如果此字符串不包含文件路径,如,test.bak”,则系统默认为当前路径,即生成的可执行文件所在目录 。
参数 nOpenFlags:用于设置访问模式,指定当打开文件时进行的动作,可以将以下所列模式用按位或,|”操作符连接起来 。 至少应有一个访问模式,
modeCreate是可选的 。 以下是常用参数列表:
CFile::modeCreate:调用构造函数构造一个新文件。
CFile::modeRead,打开文件仅供读。
CFile::modeReadWrite,打开文件供读 /写。
CFile::modeWrite,打开文件仅供写。
CFile::typeText,设置文本文件模式(只能用在子类中)。
CFile::typeBinary:设置二进制文件模式(只能用在子类中)。
参数 pError,是一个异常类的指针,可通过该类和函数的返回值来确定函数是否调用成功,如下表所示 。
6.11,文件的打开与关闭注意,参数 pError为 CFileException类型 。 而 CFileException是异常类的一种,用于检测文件操作中可能出现的错误 。 关于异常类,将在第八章进行详细的介绍 。
例如:
CFile f;
if (!f.Open(“D:\\bak\\test.txt”,CFile::modeCreate | CFile::modeWrite))
return false;
6.11,文件的打开与关闭
Perror 返回值 调用是否成功 异常类的设置
NULL True Y
NULL False N
CFileException True Y 没有变化
CFileException False N 置入错误信息
( 2) 用于打开文件的构造函数
CFile( LPCTSTR lpszFileName,UINT nOpenFlags) throw( CFileException ) ;
如:
CFile f(,D:\\bak\\test.txt”,Cfile::modeRead) ;
注意:构造函数没有返回值,当打开文件出错时只是产生一个异常 。 所以不能象函数那样通过分支语句来保证文件已打开,而应使用 TRY/CATCH
宏来判断 。
例:
CString strFileName =,D:\\bak\\test.txt”;
TRY
{
CFile f(strFileName,CFile::modeCreate | CFile::modeWrite);
}
CATCH(CfileException e)
{
#ifdef_DEBUG
afxDump<<″文件不能打开 ! ″<<e->m_cause<<″\n″;
#endif
}END_CATCH
6.11,文件的打开与关闭
( 3) 成员函数 Close
定义,void Close( ) ;
Close函数用于关闭由 Open函数打开的文件 。 使用 Open
函数打开文件后,应使用 Close函数释放文件句柄及缓冲区的资源 。
打开文件和关闭文件的例子 。
CFile f;
if (!f.Open(“D:\\bak\test.txt”,CFile::modeRead))
{
MessageBox(“打开文件失败 !,);
return ;
}
f.Close();
6.11,文件的打开与关闭
( 1) 读写函数
virtual UINT Read (void* lpBuf,UINT nCount) ; throw(CFileException);
Read函数返回值是传输到缓冲区的字节数 。
参数 lpBuf,指向用户提供的缓冲区以接收从文件中读取的数据 。
参数 nCount,为可以从文件中读出字节数的最大值 。
注意:对所有 CFile类,如果到达文件尾,则返回值可能比 nCount小 。
virtual void Write(const void* lpBuf,UINT nCount); throw (CFileException);
Write函数的参数与 Read函数的参数类似 。
参数 lpBuf,指向用户提供的缓冲区,包含将写入文件中的数据 。
参数 nCount,从缓冲区内传输的字节数 。
Write在几种情况下均产生异常,包括磁盘满的情况,磁盘为写保护状态等 。
注意,CFile类并没有提供类似 EOF之类的文件结束标志,所以文件的结束是根据 Read函数的返回值来判断的 。 Read函数返回的是实际读出的字符数,
当返回 0时,则表示文件已读完 。
6.12 文件的读写
6.12 文件读写例题(文件复制 1)
BOOL Copy(CString strSource,CString strTarget)
{
CFile fSource,fTarget;
char c[4096]; //定义 4k字节的缓冲区
nt nCount;
//打开文件
if (!fSource.Open(strSource,CFile::modeRead))
{
MessageBox(“Open Source File Fail!”);
return false;
}
if (!fTarget.Open(strTarget,CFile::modeCreate | CFile::modeWrite))
{
MessageBox(“Create Target File Fail!”);
fSource.Close();
return false;
}
//读文件到缓冲区 c
6.12 文件读写例题(文件复制 2)
struct tegStudent
{
int nCode;
char sName[10];
int nAge;
} STUDENT,* LPSTUDENT;
BOOL Copy(CString strSource,CString strTarget)
{
CFile fSource,fTarget;
//定义 STUDENT变量
STUDENT s;
int nCount;
//打开文件
if (!fSource.Open(strSource,CFile::modeRead))
{
MessageBox(“Open Source File Fail!”);
return false;
}
6.13 文件的定位
( 1 ) virtual LONG Seek(LONG lOff,UINT nFrom);
throw(CFileException);
返回值:如果要求的位置合法,则 Seek返回从文件开始的字节偏移量 。 否则值未定义,并产生 CFileException异常 。
参数 lOff:指针移动的字节数 。
参数 nFrom:指针移动的参照点,有三种取值如下:
CFile::begin,从文件开始,把指针向后移动 lOff字节 。
CFile::current,从当前位置开始,把指针向后移动 lOff字节 。
CFile::end:从文件尾开始,把指针向后移动 lOff字节 。
例:
CFile f;
LONG lOffset = 1000,lActual;
lActual = cfile.Seek(lOffset,CFile::begin);
6.13 文件的定位
( 2) void SeekToBegin( ); throw(CFileException);
函数 SeekToBegin将文件指针指向文件开始处 。
( 3) DWORD SeekToEnd( ); throw( CFileException );
函数 SeekToEnd将文件指针指向文件逻辑尾部,返回值为文件长度 ( 字节数 )
例:假设 f为已打开文件,且以 STUDENT结构 ( 定义见上例 )
为记录,下面的 GetData函数读取第 nRecord条记录的值 。
6.13 文件的定位
STUDENT GetData(CFile f,int nRecord)
{
int offset;
STUDENT s;
//计算第 nRecord条记录在文件中的位置
offset = (nRecord – 1) * sizeof(STUDENT);
//文件指针移到文件头
f.SeekToBegin();
//从当前位置移动 offset个字节
f.Seek(offset,CFile::current);
//读取记录信息
f.Read(s,sizeof(STUDENT));
return s;
}
6.13 文件的定位
( 4)
virual DWORD GetPosition()const ;throw(CFileException);
该函数返回一个 32位的无符号整型数,用于标识当前文件指针相对于文件头的偏移量 。
例:使用该函数求文件的长度 。
DWORD GetFileLength(CFile f)
{
f.SeekToEnd();
return f.GetPosition();
}
6.14 文件的状态函数
( 1) ( virtual DWORD GetLength() const; throws (CFileException);
该函数没有参数,直接返回文件以字节计的长度 。
( 2) GetFileName( ),取得文件名
( 3) GetFileTitle( ),取得文件标签
( 4) GetFilePath( ),取得文件路径
( 5) BOOL GetStatus(CFileStatus & rStatus) const;
如果指定文件的状态信息成功获取,该函数的返回值为
TRUE,否则为 FALSE。
参数 rStatus,用 于 返 回 文 件 的 信 息 。 这 里 使 用 了
CFileStatus结构来接收状态信息 。 以下是 CFileStatus结构的定义:
6.14 文件的状态函数
stuct CFileStatus
{
CTime m_ctime; //文件创建的时间
CTime m_mtime; //文件最后一次修改的时间
CTime m_atime; //最后一次访问文件并读取的时间
LONG m_size; //文件逻辑长度,以字节数表示
BYTE m_attribute; //文件属性字节
// Windows字符集表示的全文件名
TCHAR m_szFullName[MAX_PATH];
};
m_attribute成员表述文件属性,MFC提供一个 enum类型的属性,如下:
6.14 文件的状态函数
enum Attribute
{
normal=0x00,// 一般
readOnly=0x01,// 只读
hidden=0x02,// 隐藏
system=0x04,// 系统
volume=0x08,// 卷标
directory=0x10,// 目录
archive=0x20 // 归档
};
6.14 文件的状态函数例题(判断文件是否只读)
BOOL IsReadOnly(CFile f)
{
CFileStatus fs;
//注意:函数的参数为引用不是指针,所以不需要用取地址符号
f.GetStatus(fs);
if (fs,m_attribute & CFile:,readOnly == fs,m_attribute)
return true;
else
return false;
}
6.15 CFile类的静态函数
void SetReadOnly(CString strFilename)
{
CFileStatus fs;
CFile::GetStatus(strFilename,fs);
fs,m_attribute |= CFile:,readOnly;
CFile::SetStatus(strFilename,fs);
}
(1) GetStatus与 SetStatus函数
GetStatus(),用于取得指定文件的状态信息
Static BOOL PASCAL GetStatus(LPCSTR lpszFileName,CFileStatus & rStatus);
参数 LpszFileName:文件路径,可为绝对路径或为相对路径。
参数 rStatus:用于返回文件的信息。
SetStatus(),用于设置指定文件的状态信息。
Static BOOL PASCAL SetStatus(LPCSTR lpszFileName,const CFileStatus & rStatus);
例:设置文件为只读
6.15 CFile类的静态函数
(2) 函数 Remove()
函数 Remove( ) 用于删除指定的文件 。
static void PASCAL Remove( LPCTSTR lpszFileName) ; throw( CFileException) ;
参数 lpszFileName:表示所要删除文件的路径字符串 。 路径可为相对或绝对 。
说明此静态函数删除由路径指定的文件,但不可移去一个目录 。
如果相关联的文件打开或文件不可移去,则函数产生一个异常 。
这个函数等价于 DOS中的 del命令 。
例:删除文件
CString strFileName =″d:\\bak\\test.dat″;
CFile::Remove(strFileName);
6.15 CFile类的静态函数
(3) 函数 Rename()
函数 Rename( ) 用于更改指定文件的文件名 。
static void PASCAL Rename(LPCTSTR lpszOldName,LPCTSTR lpszNewName);
throw (CFleException);
参数 lpszOldName原路径 。
lpszNewName新路径 。 此函数用于改名一个指定文件 。 注意目录不可改变,这个函数等价于 DOS中的 REN命令 。
例:更改文件名
CString strSource =,d:\\bak\\test.txt”;
CString strTarget =,d:\\bak\\test1.txt”;
CFile::Rename(strSource,strTarget);
6.2 文本文件类 CStdioFile
学习目标使用 CStdioFile类进行文件读写
6.2
返回第 6章
ReadString函数的定义如下:
BOOL ReadString( CString& rString) ; throw
( CFileException ) ;
返回值:返回一个布尔型值,当无数据可读时,返回 FALSE,
否则返回 TRUE。
参数 rString:是一个对 CString对象的引用,当函数返回时,该对象包含了所读取的字符串 。
此成员函数用换行符将文本文件分为若干行,然后将文本以行为单位读出到参数 rString。 读出的数据将忽略回车 -换行符 。
6.21,CStdioFile::ReadString
WriteString函数的定义如下:
virtual void WriteString( LPCTSTR lpsz ) ;
throw( CFileException ) ;
参数 lpsz:指定一个指向存放了以空字符结尾的文本字符串的缓冲区的指针 。
说明:此成员函数将一个缓冲区中的数据写入文件,并且参数
lpsz中的所有换行符都被转换成一个硬回车 -换行符对写入 。
6.22,CStdioFile::WriteString
6.2例:拷贝文本文件的专用函数
BOOL Copy(CString strSource,CString strTarget)
{
CStdioFile fSource,fTarget;
CString strTemp;
if (!fSource.Open(strSource,CFile::modeRead))
{
MessageBox(“Open Source File Fail!”);
return false;
}
if (!fTarget.Open(strTarget,CFile::modeCreate | CFile::modeWrite))
{
MessageBox(“Create Target File Fail!”);
return false;
}
while (fSource.ReadString(strTemp))
{
//注意:加入回车符使生成的文件与原文件一致
6.3 文件查找学习目标使用 CFileFind类进行文件查找文件,
6.3
返回第 6章定义:
BOOL FindFile ( LPCTSTR pstrName = NULL,DWORD
dwUnused = 0) ;
返回值:如果成功,则返回真值,否则为假 。
参数 pstrName:指向待找文件名字符串,可包含星号,如果不填,则查找当前目录下的所有文件 。
参数 dwUnused:为保留参数,必须为 0或不填 。
注意:调用此函数只是打开一个文件查找,并未开始文件查找,
所以必须在调用至少一次 FindNextFile函数后,方可调用取得文件属性的函数,例如,GetLength( ) 。 但如果打开失败,再调 FindNextFile函数则会出错 。 所以应检查本函数的返回值 。
6.31,FindFile函数定义,BOOL FindNextFile( ) ;
返回值:如果还有文件,则返回真值;如果为最后一个文件,
则为假,
注意:调用此函数是检查是否还有文件,所以可以作为循环标志使用 。
6.32,FindNextFile函数:
6.3例:取得某目录下所有文件名
void GetFilePath(CString strPath,CStringList * pstrNameList)
{
CFileFind ff; //定义一个 CfileFind对象
BOOL bFlag;
if (!ff.FindFile(strPath)) //打开以 strPath为目标的文件查询,并检查调用是否成功
return;
while (ff.FindNextFile()) //查找下个文件
{
if (ff.IsDots())
continue;
if (ff.IsDirectory())
{
CString strTemp;
Int lie;
strTemp = ff.GetFilePath(); //取道目录的全路径
if (strTemp.Right(1) != "\\")
strTemp += "\\";
6.4 WINDOWS的文件操作简介学习目标了解 WINDOWS文件操作函数,
6.4
返回第 6章定义:
WINSHELLAPI int WINAPI
SHFileOperation( LPSHFILEOPSTRUCT lpFileOp) ;
说明:用于添加,删除,改名,移动等文件操作 。
返回值:调用成功则返回 0。
参数 lpFileOp,SHFILEOPSTRUCT结构的指针,本结构存储文件操作的信息 。 windows的很多系统结构都在定义时同时定义了指针类型,指针结构名以,LP”+结构名构成,如:
LPSHFILEOPSTRUCT 和 SHFILEOPSTRUCT 。 请注 意
SHFILEOPSTRUCT结构的定义方法 。
6.41.函数,SHFileOperation
SHFILEOPSTRUCT结构的定义,
typedef struct _SHFILEOPSTRUCT{
HWND hwnd;
UINT wFunc;
LPCSTR pFrom;
LPCSTR pTo;
FILEOP_FLAGS fFlags;
BOOL fAnyOperationsAborted;
LPVOID hNameMappings;
LPCSTR lpszProgressTitle;
} SHFILEOPSTRUCT,FAR *LPSHFILEOPSTRUCT;
成员 hwnd,用于显示文件操作信息窗体的句柄,一般填写显示信息窗体的成员变量 m_hWnd。 若不需要显示信息,也可填 NULL。
成员 wFunc:标识操作类型 。 使用以下四个宏定义:
FO_COPY,表示拷贝,从 pFrom拷贝到 pTo 。
FO_DELETE,表示删除,删除 pFrom文件(参数 pTo忽略)。
FO_MOVE,表示移动,从 pFrom移动到 pTo。
FO_RENAME,表示改名,把文件 pFrom改名为 pTo。
6.4
成员 pFrom:为原文件的文件及路径名 。 这个字符串必须以双空字符结尾,
例如,c盘根目录下的文件 a.txt,在此应表示为,c:\\a.txt\0\0”。 对于
CString类型的变量加一个,\0”字符即可 。
成员 pTo,为目标文件的文件名,在参数 wFunc为 FO_DELETE时可忽略 。
成员 fFlags:为控制文件操作的标志,一共有十几个,他们之间可通过来,|”
连接,在这里只介绍 3个常用的值 。
FOF_NOCONFIRMATION,对于一切信息提示框都按确定处理。
FOF_SILENT,不显示进度对话框。
FOF_SIMPLEPROGRESS,显示一个不显示文件名的简单的进度对话框。
通过对 FOF_NOCONFIRMATION和 FOF_SILENT的设定,我们就可以在后台默默地处理拷贝删除操作 。 而设定 FOF_SIMPLEPROGRESS,
将显示进度对话框 。
成员 fAnyOperationsAborted和 hNameMappings:主要用于处理多文件的情况 。 此处不再详细介绍 。
成员 lpszProgressTitle:当设定 FOF_SIMPLEPROGRESS时,该参数为进度对话框的标题,若没有设定 FOF_SIMPLEPROGRESS,则忽略 。
当参数 pFrom或 pTo 不包括路径时,函数默认当前系统路径,即用
GetCurrentDirectory( ) 函数取得的路径 。
6.4
6.4例:拷贝函数
BOOL Copy(CString strSource,CString strTarget)
{
CFileFind ff;
SHFILEOPSTRUCT fop; //声明 SHFILEOPSTRUCT结构
memset(&fop,0x00,sizeof(SHFILEOPSTRUCT)); //置空 SHFILEOPSTRUCT结构
if (!ff.FindFile(strSource)) //查找文件是否存在
return false;
ff.close();
strSource += '\0'; //设置为双空字符
fop.hwnd = NULL;
fop.pFrom = strSource;
fop.pTo = strTarget;
fop.wFunc = FO_COPY;
fop.fFlags = FOF_SILENT | FOF_NOCONFIRMATION;
return !::SHFileOperation(&fop); //调用函数并返回
}
定义:
WINSHELLAPI DWORD WINAPI SHGetFileInfo(
LPCTSTR pszPath,DWORD dwFileAttributes,SHFILEINFO
FAR *psfi,
UINT cbFileInfo,UINT uFlags);
参数说明:
pszPath,文件路径
dwFileAttributes,文件属性标志,一般填 0,
psfi,文件信息结构 SHFILEINFO的指针,用于存储该函数返回的文件信息 。
定义如下:
typedef struct _SHFILEINFO
{
HICON hIcon; //文件图标的句柄 。
int iIcon; //文件图标在系统图标列表中的下标 。
DWORD dwAttributes; //文件属性数组,一般忽略 。
char szDisplayName[MAX_PATH]; //文件名
char szTypeName[80]; //文件类型
} SHFILEINFO;
6.42.函数,SHGetFileInfo
cbFileInfo,文件信息结构 SHFILEINFO的长度,可用 sizeof函数取得 。
UFlags,参数标志 。 该函数提供了很多文件参数,在这里只介绍几个常用的 。 注意这里的参数可以联合使用,之间用,|”
符号连接 。
SHGFI_DISPLAYNAME:返回文件名信息,该信息将被拷贝到文件信息结构 SHFILEINFO的 szDisplayName 中 。
SHGFI_LARGEICON,返回文件的大图标 。
SHGFI_SMALLICON,返回文件的小图标 。
SHGFI_SYSICONINDEX:返回文件的图标在系统图标列表中的下标,该信息将被设置到文件信息结构 SHFILEINFO的
iIcon中 。
SHGFI_TYPENAME:返回文件类型信息,该信息将被拷贝到文件信息结构 SHFILEINFO的 szTypeName中 。
6.42.函数,SHGetFileInfo
6.4例:在某位置绘制某文件的图标
void DrawFileIcon(CDC *pDC,CPoint pt,CString strFilename)
{
SHFILEINFO sfi; //文件信息结构变量用于存放函数调用的结果
CImageList imageList; //用于取得系统的图标列表
HIAMGELIST hSysImagList //用于存放系统图标列表句柄
hSysImagList=(HIAMGELIST)::SHGetFileInfo(strFilename,0,&sfi,sizeof(SHFILEINFO),
SHGFI_SYSICONINDEX | SHGFI_SMALLICON );
imageList.Attach(hSysImageList); //得到系统图标列表
imageList.Draw(pDC,sfi.iIcon,pt,ILD_TRANSPARENT); //绘制图标
imageList.Detach(); //释放系统图标列表
}
返回第 6章