第 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.1 1,文件的打开与关闭
注意,参数 pError为 CFileException类型 。 而 CFileException是异
常类的一种, 用于检测文件操作中可能出现的错误 。 关于异
常类, 将在第八章进行详细的介绍 。
例如,
CFile f;
if (!f.Open(“D:\\bak\\test.txt”,CFile::modeCreate | CFile::modeWrite))
return false;
6.1 1,文件的打开与关闭
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.1 1,文件的打开与关闭
( 3) 成员函数 Close
定义,void Close( ) ;
Close函数用于关闭由 Open函数打开的文件 。 使用 Open
函数打开文件后, 应使用 Close函数释放文件句柄及缓冲区
的资源 。
打开文件和关闭文件的例子 。
CFile f;
if (!f.Open(“D:\\bak\test.txt”,CFile::modeRead))
{
MessageBox(“打开文件失败 !, );
return ;
}
f.Close();
6.1 1,文件的打开与关闭
( 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.1 2 文件的读写
6.1 2 文件读写例题(文件复制 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.1 2 文件读写例题(文件复制 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.1 3 文件的定位
( 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.1 3 文件的定位
( 2) void SeekToBegin( ); throw(CFileException);
函数 SeekToBegin将文件指针指向文件开始处 。
( 3) DWORD SeekToEnd( ); throw( CFileException );
函数 SeekToEnd将文件指针指向文件逻辑尾部, 返回值为文件
长度 ( 字节数 )
例:假设 f为已打开文件, 且以 STUDENT结构 ( 定义见上例 )
为记录, 下面的 GetData函数读取第 nRecord条记录的值 。
6.1 3 文件的定位
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.1 3 文件的定位
( 4)
virual DWORD GetPosition()const ;throw(CFileException);
该函数返回一个 32位的无符号整型数, 用于标识当前文件指
针相对于文件头的偏移量 。
例:使用该函数求文件的长度 。
DWORD GetFileLength(CFile f)
{
f.SeekToEnd();
return f.GetPosition();
}
6.1 4 文件的状态函数
( 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.1 4 文件的状态函数
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.1 4 文件的状态函数
enum Attribute
{
normal=0x00,// 一般
readOnly=0x01,// 只读
hidden=0x02,// 隐藏
system=0x04,// 系统
volume=0x08,// 卷标
directory=0x10,// 目录
archive=0x20 // 归档
};
6.1 4 文件的状态函数例题(判断文件是否只读)
BOOL IsReadOnly(CFile f)
{
CFileStatus fs;
//注意:函数的参数为引用不是指针, 所以不需要用取地址符号
f.GetStatus(fs);
if (fs,m_attribute & CFile:,readOnly == fs,m_attribute)
return true;
else
return false;
}
6.1 5 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.1 5 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.1 5 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.2 1,CStdioFile::ReadString
WriteString函数的定义如下,
virtual void WriteString( LPCTSTR lpsz ) ;
throw( CFileException ) ;
参数 lpsz:指定一个指向存放了以空字符结尾的文本字符串的
缓冲区的指针 。
说明:此成员函数将一个缓冲区中的数据写入文件, 并且参数
lpsz中的所有换行符都被转换成一个硬回车 -换行符对写入 。
6.2 2,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.3 1,FindFile函数
定义,BOOL FindNextFile( ) ;
返回值:如果还有文件, 则返回真值;如果为最后一个文件,
则为假,
注意:调用此函数是检查是否还有文件, 所以可以作为循环标
志使用 。
6.3 2,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.4 1.函数,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.4 2.函数,SHGetFileInfo
cbFileInfo,文件信息结构 SHFILEINFO的长度, 可用 sizeof函
数取得 。
UFlags,参数标志 。 该函数提供了很多文件参数, 在这里只介
绍几个常用的 。 注意这里的参数可以联合使用, 之间用, |”
符号连接 。
SHGFI_DISPLAYNAME:返回文件名信息, 该信息将被拷贝
到文件信息结构 SHFILEINFO的 szDisplayName 中 。
SHGFI_LARGEICON,返回文件的大图标 。
SHGFI_SMALLICON,返回文件的小图标 。
SHGFI_SYSICONINDEX:返回文件的图标在系统图标列表中
的下标, 该信息将被设置到文件信息结构 SHFILEINFO的
iIcon中 。
SHGFI_TYPENAME:返回文件类型信息, 该信息将被拷贝到
文件信息结构 SHFILEINFO的 szTypeName中 。
6.4 2.函数,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章
内容摘要,
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.1 1,文件的打开与关闭
注意,参数 pError为 CFileException类型 。 而 CFileException是异
常类的一种, 用于检测文件操作中可能出现的错误 。 关于异
常类, 将在第八章进行详细的介绍 。
例如,
CFile f;
if (!f.Open(“D:\\bak\\test.txt”,CFile::modeCreate | CFile::modeWrite))
return false;
6.1 1,文件的打开与关闭
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.1 1,文件的打开与关闭
( 3) 成员函数 Close
定义,void Close( ) ;
Close函数用于关闭由 Open函数打开的文件 。 使用 Open
函数打开文件后, 应使用 Close函数释放文件句柄及缓冲区
的资源 。
打开文件和关闭文件的例子 。
CFile f;
if (!f.Open(“D:\\bak\test.txt”,CFile::modeRead))
{
MessageBox(“打开文件失败 !, );
return ;
}
f.Close();
6.1 1,文件的打开与关闭
( 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.1 2 文件的读写
6.1 2 文件读写例题(文件复制 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.1 2 文件读写例题(文件复制 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.1 3 文件的定位
( 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.1 3 文件的定位
( 2) void SeekToBegin( ); throw(CFileException);
函数 SeekToBegin将文件指针指向文件开始处 。
( 3) DWORD SeekToEnd( ); throw( CFileException );
函数 SeekToEnd将文件指针指向文件逻辑尾部, 返回值为文件
长度 ( 字节数 )
例:假设 f为已打开文件, 且以 STUDENT结构 ( 定义见上例 )
为记录, 下面的 GetData函数读取第 nRecord条记录的值 。
6.1 3 文件的定位
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.1 3 文件的定位
( 4)
virual DWORD GetPosition()const ;throw(CFileException);
该函数返回一个 32位的无符号整型数, 用于标识当前文件指
针相对于文件头的偏移量 。
例:使用该函数求文件的长度 。
DWORD GetFileLength(CFile f)
{
f.SeekToEnd();
return f.GetPosition();
}
6.1 4 文件的状态函数
( 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.1 4 文件的状态函数
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.1 4 文件的状态函数
enum Attribute
{
normal=0x00,// 一般
readOnly=0x01,// 只读
hidden=0x02,// 隐藏
system=0x04,// 系统
volume=0x08,// 卷标
directory=0x10,// 目录
archive=0x20 // 归档
};
6.1 4 文件的状态函数例题(判断文件是否只读)
BOOL IsReadOnly(CFile f)
{
CFileStatus fs;
//注意:函数的参数为引用不是指针, 所以不需要用取地址符号
f.GetStatus(fs);
if (fs,m_attribute & CFile:,readOnly == fs,m_attribute)
return true;
else
return false;
}
6.1 5 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.1 5 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.1 5 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.2 1,CStdioFile::ReadString
WriteString函数的定义如下,
virtual void WriteString( LPCTSTR lpsz ) ;
throw( CFileException ) ;
参数 lpsz:指定一个指向存放了以空字符结尾的文本字符串的
缓冲区的指针 。
说明:此成员函数将一个缓冲区中的数据写入文件, 并且参数
lpsz中的所有换行符都被转换成一个硬回车 -换行符对写入 。
6.2 2,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.3 1,FindFile函数
定义,BOOL FindNextFile( ) ;
返回值:如果还有文件, 则返回真值;如果为最后一个文件,
则为假,
注意:调用此函数是检查是否还有文件, 所以可以作为循环标
志使用 。
6.3 2,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.4 1.函数,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.4 2.函数,SHGetFileInfo
cbFileInfo,文件信息结构 SHFILEINFO的长度, 可用 sizeof函
数取得 。
UFlags,参数标志 。 该函数提供了很多文件参数, 在这里只介
绍几个常用的 。 注意这里的参数可以联合使用, 之间用, |”
符号连接 。
SHGFI_DISPLAYNAME:返回文件名信息, 该信息将被拷贝
到文件信息结构 SHFILEINFO的 szDisplayName 中 。
SHGFI_LARGEICON,返回文件的大图标 。
SHGFI_SMALLICON,返回文件的小图标 。
SHGFI_SYSICONINDEX:返回文件的图标在系统图标列表中
的下标, 该信息将被设置到文件信息结构 SHFILEINFO的
iIcon中 。
SHGFI_TYPENAME:返回文件类型信息, 该信息将被拷贝到
文件信息结构 SHFILEINFO的 szTypeName中 。
6.4 2.函数,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章