MFC教程(11)-- MFC下的文件类

文件操作的方法

  使用Visual C++编程,有如下方法进行文件操作:

  (1)使用标准C运行库函数,包括fopen、fclose、fseek等。

  (2)使用Win16下的文件和目录操作函数,如lopen、lclose、lseek等。不过,在Win32下,这些函数主要是为了和Win16向后兼容。

  (3)使用Win32下的文件和目录操作函数,如CreateFile,CopyFile,DeleteFile,FindNextFile,等等。

  Win32下,打开和创建文件都由CreateFile完成,成功的话,得到一个Win32下的句柄,这不同于“C”的fopen返回的句柄。在Win16下,该句柄和C运行库文件操作函数相容。但在Win32下,“C”的文件操作函数不能使用该句柄,如果需要的话,可以使用函数_open_osfhandle从Win32句柄得到一个“C”文件函数可以使用的文件句柄。

  关闭文件使用Win32的CloseHandle。

  在Win32下,CreateFile可以操作的对象除了磁盘文件外,还包括设备文件如通讯端口、管道、控制台输入、邮件槽等等。

  (4)使用CFile和其派生类进行文件操作。CFile从CObject派生,其派生类包括操作文本文件的CStdioFile,操作内存文件的CmemFile,等等。

  CFile是建立在Win32的文件操作体系的基础上,它封装了部分Win32文件操作函数。

  最好是使用CFile类(或派生类)的对象来操作文件,必要的话,可以从这些类派生自己的文件操作类。统一使用CFile的界面可以得到好的移植性。

 

  MFC的文件类

  MFC用一些类来封装文件访问的Win32 API。以CFile为基础,从CFile派生出几个类,如CStdioFile,CMemFile,MFC内部使用的CMiororFile,等等。

  CFile的结构

  CFile定义的枚举类型

 

 

  CFile类定义了一些和文件操作相关的枚举类型,主要有四种:OpenFlags,Attribute,SeekPosition,hFileNull。下面,分别解释这些枚举类型。

  OpenFlags

  OpenFlags定义了13种文件访问和共享模式:

  enum OpenFlags {

  //第一(从右,下同)至第二位,打开文件时访问模式,读/写/读写

  modeRead = 0x0000,

  modeWrite = 0x0001,

  modeReadWrite = 0x0002,

  shareCompat = 0x0000, //32位MFC中没用

  //第五到第七位,打开文件时的共享模式

  shareExclusive = 0x0010,//独占方式,禁止其他进程读写

  shareDenyWrite = 0x0020,//禁止其他进程写

  shareDenyRead = 0x0030,//禁止其他进程读

  shareDenyNone = 0x0040,//允许其他进程写

  //第八位,打开文件时的文件继承方式

  modeNoInherit = 0x0080,//不允许子进程继承

  //第十三、十四位,是否创建新文件和创建方式

  modeCreate = 0x1000,//创建新文件,文件长度0

  modeNoTruncate = 0x2000,//创建新文件时如文件已存在则打开

  //第十五、十六位,文件以二进制或者文本方式打开,在派生类CStdioFile中用

  typeText = 0x4000,

  typeBinary = (int)0x8000

  };

 

  Attribute

  Attribute定义了文件属性:正常、只读、隐含、系统文件,文件或者目录等。

  enum Attribute {

  normal = 0x00,

  readOnly = 0x01,

  hidden = 0x02,

  system = 0x04,

  volume = 0x08,

  directory = 0x10,

  archive = 0x20

  }

 

  SeekPosition

  SeekPosition定义了三种文件位置:头、尾、当前:

  enum SeekPosition{

  begin = 0x0,

  current = 0x1,

  end = 0x2

  };

 

  hFileNull

  hFileNull定义了空文件句柄

  enum { hFileNull = -1 };

  CFile的其他一些成员变量

  CFile除了定义枚举类型,还定义了一些成员变量。例如:

  UINT m_hFile

  该成员变量是public访问属性,保存::CreateFile返回的操作系统的文件句柄。MFC重载了运算符号HFILE来返回m_hFile,这样在使用HFILE类型变量的地方可以使用CFile对象。

  BOOL m_bCloseOnDelete;

  CString m_strFileName;

  这两个成员变量是protected访问属性。m_bCloseOnDelete用来指示是否在关闭文件时删除CFile对象;m_strFileName用来保存文件名。

 

  CFile的成员函数

  CFile的成员函数实现了对Win32文件操作函数的封装,完成以下动作:打开、创建、关闭文件,文件指针定位,文件的锁定与解锁,文件状态的读取和修改,等等。其中,用到了m_hFile文件句柄的一般是虚拟函数,和此无关的一般是静态成员函数。一般地,成员函数被映射到对应的Win32函数,如表11-1所示。

  表11-1 CFile函数对Win32文件函数的封装

  虚拟

  静态

  成员函数

  对应的Win32函数

  文件的创建、打开、关闭

  √

 

  Abort

  CloseHandle

  √

 

  Duplicate

  DuplicateHandle

  √

 

  Open

  CreateFile

  √

 

  Close

  CloseHandle

  文件的读写

  √

 

  Read

  ReadFile

  

  ReadHuge(向后兼容)

  调用Read成员函数

  √

 

  Write

  WriteFile

  

  WriteHuage(向后兼容)

  调用Write成员函数

  √

 

  Flush

  FlushFileBuffers

  文件定位

  √

 

  Seek

  SetFilePointer

  

  SeekToBegin

  调用Seek成员函数

  

  SeekToEnd

  调用Seek成员函数

  √

 

  GetLength

  调用Seek成员函数

  √

 

  SetLength

  SetEndOfFile

  文件的锁定/解锁

  √

 

  LockRange

  LockFile

  √

 

  UnlockRange

  UnlockFile

  文件状态操作函数

  √

 

  GetPosition

  SetFilePointer

  

  GetStatus(CFileStatus&)

  GetFileTime,GetFileSize等

 

  √

  GetStatus(LPSTR lpszFileName CFileStatus&)

  FindFirstFile

  √

 

  GetFileName

  不是简单地映射到某个函数

  √

 

  GetFileTitle

 

  √

 

  GetFilePath

 

  √

 

  SetFilePath

 
 

  √

  SetStatus

 

  改名和删除

 

  √

  Rename

  MoveFile

 

  √

  Remove

  DeleteFile

  CFile的部分实现

  这里主要讨论CFile对象的构造函数和文件的打开/创建的过程。

  构造函数

  CFile有如下几个构造函数:

  CFile()

  缺省构造函数,仅仅构造一个CFile对象,还必须使用Open成员函数来打开文件。

  CFile(int hFile)

  已经打开了一个文件hFile,在此基础上构造一个CFile对象来给它打包。HFile将被赋值给CFile的成员变量m_hFile。

  CFile(LPCTSTR lpszFileName, UINT nOpenFlags)

  指定一个文件名和文件打开方式,构造CFile对象,调用Open打开/创建文件,把文件句柄保存到m_hFile。

  打开/创建文件

  Open的原型如下:

  BOOL CFile::Open(LPCTSTR lpszFileName, UINT nOpenFlags,

  CFileException* pException)

  Open调用Win32函数::CreateFile打开文件,并把文件句柄保存到成员变量m_hFile中。

  CreateFile函数的原型如下:

  HANDLE CreateFile(

  LPCTSTR lpFileName,// pointer to name of the file

  DWORD dwDesiredAccess,// access (read-write) mode

  DWORD dwShareMode,// share mode

  LPSECURITY_ATTRIBUTES lpSecurityAttributes, //pointer to security descriptor

  DWORD dwCreationDistribution,// how to create

  DWORD dwFlagsAndAttributes,// file attributes

  HANDLE hTemplateFile// handle to file with attributes to copy

  );

  显然,Open必须把自己的两个参数lpszFileName和nOpenFlags映射到CreateFile的七个参数上。

  从OpenFlags的定义可以看出,(nOpenFlags & 3)表示了读写标识,映射成变量dwAccess,可以取值为Win32的GENERIC_READ、GENERIC_WRITE、GENERIC_READ|GENERIC_WRITE。

  (nOpenFlags & 0x70)表示了共享模式,映射成变量dwShareMode,可以取值为Win32的FILE_SHARE_READ、FILE_SHARE_WRITE、FILE_SHARE_WRITE|FILE_SHARE_READ。

  Open定义了一个局部的SECURITY_ATTRIBUTES变量sa,(nOpenFlags & 0x80)被赋值给sa.bInheritHandle。

  (nOpenFlags & modeCreate)表示了创建方式,映射成变量dwCreateFlag,可以取值为Win32的OPEN_ALWAYS、CREATE_ALWAYS、OPEN_EXISTING。

  在生成了上述参数之后,先调用::CreateFile:

  HANDLE hFile =::CreateFile(lpszFileName,

  dwAccess, dwShareMode, &sa,

  dwCreateFlag, FILE_ATTRIBUTE_NORMAL, NULL);

  然后,hFile被赋值给成员变量m_hFile,m_bCloseOnDelete被设置为TRUE。

  由上可以看出,CFile打开(创建)一个文件时大大简化了:: CreateFile函数的复杂性,即只需要指定一个文件名、一个打开文件的参数即可。若该参数指定为0,则表示以只读方式打开一个存在的文件,独占使用,不允许子进程继承。

  在CFile对象使用时,如果它是在堆中分配的,则应该销毁它;如果在栈中分配的,则CFile对象将被自动销毁。销毁时析构函数被调用,析构函数是虚拟函数。若m_bCloseOnDelete为真且m_hFile非空,则析构函数调用Close关闭文件。

  至于其他CFile成员函数的实现,这里不作分析了。

  CFile的派生类

  这里主要简要地介绍CStdioFile和CmemFile及CFileFind。

  CStdioFile

  CStdioFile对文本文件进行操作。

  CStdioFile定义了新的成员变量m_pStream,类型是FILE*。在打开或者创建文件时,使用_open_osfhandle从m_hFile(Win32文件句柄)得到一个“C”的FILE类型的文件指针,然后,在文件操作中,使用“C”的文件操作函数。例如,读文件使用_fread,而不是::ReadFile,写文件使用了_fwrite,而不是::WriteFile,等等。m_hFile是CFile的成员变量。

  另外,CStdioFile不支持CFile的Dumplicate、LockRange、UnlockRange操作,但是实现了两个新的操作ReadString和WriteString。

 

  CMemFile

  CMemFile把一块内存当作一个文件来操作,所以,它没有打开文件的操作,而是设计了Attach和Detach用来分配或者释放一块内存。相应地,它提供了Alloc、Free虚拟函数来操作内存文件,它覆盖了Read、Write来读写内存文件。

 

  CFileFind

  为了方便文件查找,MFC把有关功能归结成为一个类CFileFind。CFileFind派生于CObject类。首先,它使用FindFile和FineNextFile包装了Win32函数::FindFirstFile和::FindNextFile;其次,它提供了许多函数用来获取文件的状态或者属性。

  使用CFileStatus结构来描述文件的属性,其定义如下:

  struct CFileStatus

  {

  CTime m_ctime; // 文件创建时间

  CTime m_mtime; // 文件最近一次修改时间

  CTime m_atime; // 文件最近一次访问时间

  LONG m_size; // 文件大小

  BYTE m_attribute; // 文件属性

  BYTE _m_padding; // 没有实际含义,用来增加一个字节

  TCHAR m_szFullName[_MAX_PATH]; //绝对路径

  #ifdef _DEBUG

  //实现Dump虚拟函数,输出文件属性

  void Dump(CDumpContext& dc) const;

  #endif

  };

  例如:

  CFileStatus status;

  pFile->GetStatus(status);

  #ifdef _DEBUG

  status.dump(afxDump);

  #endif

 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
第1章 MFC概述 1 1.1 MFC是一个编程框架 1 1.1.1 封装 1 1.1.2 继承 2 1.1.3 虚拟函数和动态约束 2 1.1.4 MFC的宏观框架体系 2 1.2 MDI应用程序的构成 3 1.2.1 构成应用程序的对象 3 1.2.2 构成应用程序的对象之间的关系 5 1.2.3 构成应用程序的文件 5 第2章 MFC和Win32 9 2.1 MFC Object和Windows Object的关系 9 2.2 Windows Object 12 2.2.1 Windows的注册 12 2.2.2 MFC窗口CWnd 15 2.2.3 在MFC下创建一个窗口对象 17 2.2.4 MFC窗口的使用 18 2.2.5 在MFC下窗口的销毁 19 2.3 设备描述表 20 2.3.1 设备描述表概述 20 2.3.2 设备描述表在MFC中的实现 22 2.3.3 MFC设备描述表的使用 24 2.4 GDI对象 25 第3章 CObject 28 3.1 CObject的结构 28 3.2 CObject的特性 30 3.3 实现CObject特性的机制 32 3.3.1 DECLARE_DYNAMIC等宏的定义 32 3.3.2 CruntimeClass的结构与功能 35 3.3.3 动态信息、动态创建的原理 38 3.3.4 序列化的机制 39 第4章 消息映射的实现 42 4.1 Windows消息概述 42 4.1.1 消息的分 42 4.1.2 消息结构和消息处理 42 4.2 消息映射的定义和实现 44 4.2.1 MFC处理的三消息 44 4.2.2 MFC消息映射的实现方法 45 4.2.3 在声明与实现的内部 46 4.2.3.1 消息映射声明的解释 47 4.2.3.2 消息映射实现的解释 49 4.2.4 消息映射宏的种 51 4.3 CcmdTarget 54 4.4 MFC窗口过程 55 4.4.1 MFC窗口过程的指定 56 4.4.2 对Windows消息的接收和处理 58 4.4.2.1 从窗口过程到消息映射 59 4.4.2.2 Windows消息的查找和匹配 60 4.4.2.3 Windows消息处理函数的调用 62 4.4.2.4 消息映射机制完成虚拟函数功能的原理 63 4.4.3 对命令消息的接收和处理 64 4.4.3.1 MFC标准命令消息的发送 64 4.4.3.2 命令消息的派发和消息的多次处理 67 4.4.3.3 一些消息处理的OnCmdMsg的实现 69 4.4.3.4 一些消息处理的OnCommand的实现 71 4.4.4 对控制通知消息的接收和处理 72 4.4.4.1 WM_COMMAND控制通知消息的处理 72 4.4.4.2 WM_NOTIFY消息及其处理: 73 4.4.4.3 消息反射 74 4.4.5 对更新命令的接收和处理 77 4.4.5.1 实现方法 77 4.4.5.2 状态更新命令消息 78 4.4.5.3 CCmdUI 79 4.4.5.4 自动更新用户接口对象状态的机制 80 4.5 消息的预处理 82 4.6 MFC消息映射的回顾 83 第5章 MFC对象的创建 85 5.1 MFC对象的关系 85 5.1.1 创建关系 85 5.1.2 交互作用关系 86 5.2 MFC提供的接口 87 5.2.1 虚拟函数接口 87 5.2.2 消息映射方法和标准命令消息 91 5.3 MFC对象的创建过程 94 5.3.1 应用程序中典型对象的结构 94 5.3.1.1 应用程序的成员变量 95 5.3.1.2 CDocument的成员变量 97 5.3.1.3 文档模板的属性 97 5.3.2 WinMain入口函数 99 5.3.2.1 WinMain流程 99 5.3.2.2 MFC空闲处理 101 5.3.3 SDI应用程序的对象创建 102 5.3.3.1 文档模板的创建 102 5.3.3.2 文件的创建或者打开 103 5.3.3.3 SDI边框窗口的创建 112 5.3.3.4 视的创建 115 5.3.3.5 窗口初始化 116 5.3.3.6 视的初始化 120 5.3.3.7 激活边框窗口(处理WM_ACTIVE) 121 5.3.3.8 SDI流程的回顾 122 5.3.4 MDI程序的对象创建 123 5.3.4.1 有别于SDI的主窗口加载过程 124 5.3.4.2 MDI子窗口、视、文档的创建 125 5.3.4.3 MDI子窗口的初始化和窗口的激活 127 第6章 应用程序的退出 131 6.1 边框窗口对WM_CLOSE的处理 131 6.2 窗口的销毁过程 135 6.2.1 DestroyWindow 135 6.2.2 处理WM_DESTROY消息 136 6.2.3 处理WM_NCDESTROY消息 136 6.3 SDI窗口、MDI主、子窗口的关闭 137 第7章 MFC的DLL 139 7.1 DLL的背景知识 139 7.2 调用约定 141 7.2.1 MFC的DLL应用程序的类型 142 7.3 DLL的几点说明 143 7.4 输出函数的方法 145 第8章 MFC的进程和线程 148 8.1 Win32的进程和线程概念 148 8.2 Win32的进程处理简介 148 8.2.1 进程的创建 148 8.2.2 进程的终止 149 8.3 Win32的线程 150 8.3.1 线程的创建 150 8.3.2 线程的终止 150 8.3.3 线程局部存储 151 8.4 线程同步 152 8.4.1 同步对象 152 8.4.2 等待函数 153 8.5 MFC的线程处理 154 8.5.1 创建用户界面线程 155 8.5.2 创建工作者线程 155 8.5.3 AfxBeginThread 155 8.5.4 CreateThread和_AfxThreadEntry 157 8.5.5 线程的结束 160 8.5.6 实现线程的消息循环 161 第9章 MFC的状态 163 9.1 模块状态 163 9.2 模块、进程和线程状态的数据结构 164 9.2.1 层次关系 164 9.2.2 CNoTrackObject 166 9.2.3 AFX_MODULE_STATE 166 9.2.4 _AFX_BASE_MODULE_STATE 169 9.2.5 _AFX_THREAD_STATE 169 9.2.6 AFX_MODULE_THREAD_STATE 171 9.3 线程局部存储机制和状态的实现 172 9.3.1 CThreadSlotData和_afxThreadData 173 9.3.1.1 CThreadSlotData的定义 173 9.3.1.2 CThreadSlotData的一些数据成员 174 9.3.1.3 _afxThreadData 175 9.3.2 线程状态_afxThreadState 176 9.3.3 进程模块状态afxBaseModuleState 178 9.3.4 状态对象的创建 180 9.3.4.1 状态对象的创建过程 180 9.3.4.2 创建过程所涉及的几个重要函数的算法 183 9.4 管理状态 184 9.4.1 模块状态切换 184 9.4.2 扩展DLL的模块状态 186 9.4.2.1 _AFX_EXTENSION_MODULE 187 9.4.2.2 扩展DLL的初始化函数 188 9.4.3 核心MFC DLL 190 9.4.4 动态链接的规则DLL的模块状态的实现 190 9.5 状态信息的作用 192 9.5.1.1 模块信息的保存和管理 192 9.5.2 MFC资源、运行信息的查找 193 9.5.3 模块信息的显示 194 9.5.4 模块-线程状态的作用 196 9.5.4.1 只能访问本线程MFC对象的原因 196 9.5.4.2 实现MFC对象和Windows对象之间的映射 196 9.5.4.3 临时对象的处理 199 9.6 状态对象的删除和销毁 199 第10章 内存分配方式和调试机制 202 10.1 M内存分配 202 10.1.1 内存分配函数 202 10.1.2 C++的new 和 delete操作符 204 10.2 调试手段 204 10.2.1 C运行库提供和支持的调试功能 204 10.2.2 MFC提供的调试手段 205 10.2.3 内存诊断 208 第11MFC下的文件 210 11.1 文件操作的方法 210 11.2 MFC文件 210 11.2.1 CFile的结构 211 11.2.1.1 CFile定义的枚举类型 211 11.2.1.2 CFile的其他一些成员变量 212 11.2.1.3 CFile的成员函数 212 11.2.2 CFile的部分实现 213 11.2.3 CFile的派生 215 第12章 对话框和对话框CDialog 217 12.1 模式和无模式对话框 217 12.1.1 模式对话框 217 12.1.2 无模式对话框 218 12.2 对话框的MFC实现 219 12.2.1 CDialog的设计和实现 219 12.2.1.1 CDialog的成员变量 219 12.2.1.2 CDialog的成员函数: 219 12.2.2 MFC模式对话框的实现 220 12.2.2.1 MFC对话框过程 220 12.2.2.2 模式对话框窗口过程 221 12.2.2.3 使用原对话框窗口过程作消息的缺省处理 225 12.2.2.4 Dialog命令消息和控制通知消息的处理 226 12.2.2.5 消息预处理和Dialog消息 228 12.2.2.6 模式对话框的消息循环 229 12.2.3 对话框的数据交换 233 12.2.3.1 数据交换的方法 233 12.2.3.2 CDataExchange 234 12.2.3.3 数据交换和验证函数 236 12.2.3.4 UpdateData函数 239 12.3 无模式对话框 240 12.3.1 CScrollView 240 12.3.2 CFormView 242 12.3.2.1 CFormView的创建 243 12.3.2.2 CFormView的消息预处理 245 12.3.2.3 CFormView的输入焦点 247 第13章 MFC工具条和状态栏 248 13.1 Windows控制窗口 248 13.2 MFC的工具条和状态栏 249 13.2.1 控制窗口的创建 251 13.2.1.1 PreCreateWindow 251 13.2.1.2 控制条的窗口创建 253 13.2.2 控制条的销毁 259 13.2.3 处理控制条的位置 259 13.2.3.1 计算控制条位置的过程和算法 259 13.2.3.2 CFrameWnd的虚拟函数RecalcLayout 260 13.2.3.3 CWnd的成员函数RepositionBars 262 13.2.4 工具条、状态栏和边框窗口的接口 265 13.2.4.1 应用程序在状态栏中显示信息 265 13.2.4.2 状态栏显示菜单项的提示信息 268 13.2.4.3 控制条的消息分发处理 270 13.2.4.4 Tooltip 275 13.2.4.5 禁止和允许 279 13.2.4.6 显示或者隐藏工具栏和状态栏 285 13.2.5 泊位和漂浮 286 第14章 SOCKET的设计和实现 288 14.1 WinSock基本知识 288 14.1.1 WinSock API 288 14.1.2 Socket的使用 290 14.2 MFC对WinSockt API的封装 291 14.2.1 CAsyncSocket 291 14.2.2 socket对象的创建和捆绑 292 14.2.3 异步网络事件的处理 296 14.3 CSocket 297 14.4 CSocketFile 299
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值