96SEO 2026-02-20 07:13 0
。

Windows提供了一类API函数来读、写和管理磁盘文件。
MFC将这些函数转化为一个面向对象的类——CFile#xff0c;它允许将文件视为可以由CFile成员函数操作的对象#xff0c;如Read和Write等。
CFile类实现…文件的输入输出I/O服务是操作系统的重要部分。
Windows提供了一类API函数来读、写和管理磁盘文件。
MFC将这些函数转化为一个面向对象的类——CFile它允许将文件视为可以由CFile成员函数操作的对象如Read和Write等。
CFile类实现了程序开发者执行底层文件I/O需要的大部分功能。
并不是在任何时候使用CFile类都是方便的特别是要与底层设备如COM口、设备驱动进行交互的时候所以本节主要讨论管理文件的API函数。
事实上了解这些函数之后自然就会使用CFile类了。
使用API函数读写文件时首先要使用CreateFile函数创建文件对象即打开文件调用成功会返回文件句柄然后以此句柄为参数调用ReadFile和WriteFile函数进行实际的读写操作最后调用CloseHandle函数关闭不再使用的文件对象句柄。
CreateFile是一个功能相当强大的函数Windows下的底层设备差不多都是由它打开的。
它可以创建或打开文件、目录、物理磁盘、控制台缓冲区、邮槽和管道等。
调用成功后函数返回能够用来访问此对象的句柄其原型如下。
1lpFileName参数是要创建或打开的对象的名称。
如果打开文件直接在这里指定文件名称即可如果操作对象是第一个串口则要指定“COM1”为文件名然后就可以像操作文件一样操作串口了如果要打开本地电脑上的一个服务要以“\\.\服务名称”为文件名其中的“.”代表本地机器也可以使用CreateFile打开网络中其他主机上的文件此时的文件名应该是“\\主机名\共享目录名\文件名”。
2dwDesiredAcces参数是访问方式它指定了要对打开的对象进行何种操作。
指定GENERIC_READ标志表示以只读方式打开指定GENERIC_WRITE标志表示以只写方式打开指定这两个值的组合表示要同时对打开的对象进行读写操作。
3dwShareMode参数指定了文件对象的共享模式表示文件打开后是否允许其他代码以某种方式再次打开这个文件它可以是下列值的一个组合
允许以后的程序代码以写方式打开文件4dwCreationDisposition参数指定了当文件已存在或者不存在时系统采取的动作。
在这里设置不同的标志就可以决定究竟是要打开文件还是要创建文件。
参数的可能取值如下
5dwFlagsAndAttributes参数用来指定新建文件的属性和标志。
文件属性可以是下面这些值的组合
存中以加快存取速度。
使用完后要尽快将它删除此参数还可同时指定对文件的操作方式下面是一些比较常用的方式
立即写入硬盘6hTemplateFile参数指定了一个文件模板句柄。
系统会复制该文件模板的所有属性到当前创建的文件中。
Windows
打开或创建文件成功时函数返回文件句柄失败时返回INVALID_HANDLE_VALUE1。
如果想再详细了解失败的原因可以继续调用GetLastError函数。
用不同的参数组合调用CreateFile函数可以完成不同的功能例如下面的代码为读取数据打开了一个存在的文件。
要关闭打开的文件直接以CreateFile返回的文件句柄调用CloseHandle函数即可。
系统为每个打开的文件维护一个文件指针指定对文件的下一个读写操作从什么位置开始。
随着数据的读出或写入文件指针也随之移动。
当文件刚被打开时文件指针处于文件的头部。
有时候需要随机读取文件内容这就需要先调整文件指针SetFilePointer函数提供了这个功能原型如下。
dwMoveMethod参数指明了从什么地方开始移动可以是下面的一个值
开始移动位置是文件的结尾即从文件尾开始移动函数执行失败返回1否则返回新的文件指针的位置。
SetEndOfFile函数可以截断或者扩展文件。
该函数移动指定文件的结束标志end-of-fileEOF到文件指针指向的位置。
如果文件扩展旧的EOF位置和新的EOF位置间的内容是未定义的。
SetEndOfFile函数的用法如下。
截断或者扩展文件时要首先调用SetFilePointer移动文件指针然后再调用SetFilePointer函数设置新的文件指针位置为EOF。
读写文件的函数是ReadFile和WriteFile这两个函数既可以同步读写文件又可以异步读写文件。
而函数ReadFileEx和WriteFileEx只能异步读写文件。
从文件读取数据的函数是ReadFile向文件写入数据的函数是WriteFile操作的开始位置由文件指针指定。
这两个函数的原型如下。
当用WriteFile写文件时写入的数据通常被Windows暂时保存在内部的高速缓存中等合适的时候再一并写入磁盘。
如果一定要保证所有的数据都已经被传送可以强制使用FlushFileBuffers函数来清空数据缓冲区函数的惟一参数是要操作的文件句柄。
当对文件数据的一致性要求较高时为了防止程序在写入的过程中其他进程刚好在读取写入区域的内容可以对已打开文件的某个部分进行加锁这就可以防止其他进程对该区域进行读写。
加锁和解锁的函数是LockFile和UnlockFile它们的原形如下。
dwFileOffsetLow和dwFileOffsetHigh参数组合起来指定了加锁区域的开始位置nNumberOfBytesToLockLow和nNumberOfBytesToLockHigh参数组合起来指定了加锁区域的大小。
这两个参数都指定了一个64位的值在Win32中只使用32位就够了。
如果加锁文件的进程终止或者文件关闭时还未解锁操作系统会自动解除对文件的锁定。
但是操作系统解锁文件花费的时间取决于当前可用的系统资源。
因此进程终止时最好显式地解锁所有已锁定的文件以免造成这些文件无法访问。
Windows下的许多对象都称之为文件如果想知道一个文件句柄究竟对应什么对象可以使用GetFileType函数原型如下。
如果确定操作的对象是磁盘文件还可以使用GetFileSize函数取得这个文件的长度。
函数执行成功将返回文件大小的低双字如果lpFileSizeHigh参数不是NULL函数将文件大小的高双字放入它指向的DWORD变量中。
如果函数执行失败并且lpFileSizeHigh是NULL返回值将是INVALID_FILE_SIZE如果函数执行失败但lpFileSizeHigh不是NULL返回值是INVALID_FILE_SIZE进一步调用GetLastError会返回不为NO_ERROR的值。
如果返回值是INVALID_FILE_SIZE应用程序必须调用GetLastError来确定函数调用是否成功。
原因是当lpFileSizeHigh不为NULL或者文件大小为0xffffffff时函数虽然调用成功了但依然会返回INVALID_FILE_SIZE。
这种情况下GetLastError会返回NO_ERROR来响应成功。
如果要查看文件或者目录的属性可以使用GetFileAttributes函数它会返回一系列FAT风格的属性信息。
lpFileName指定了文件或者的属性信息可以是下列取值的组合
这些属性对目录也同样适用。
INVALID_FILE_ATTRIBUTES0xFFFFFFFF是函数执行失败后的返回值。
下面是快速检查某个文件或目录是否存在的自定义函数可以将它用在自己的工程中。
GetFileAttributes(lpszFileName);
第2个参数bIsDirCheck指定要检查的对象是目录还是文件。
与GetFileAttributes相对应的函数是SetFileAttributes这个函数用来设置文件属性。
拷贝文件的函数是CopyFile和CopyFileEx其作用都是复制一个存在的文件到一个新文件中。
CopyFile函数的用法如下。
CopyFileEx函数的附加功能是允许指定一个回调函数在拷贝过程中函数每拷贝完一部分数据就会调用回调函数。
用户在回调函数中可以指定是否停止拷贝还可以显示进度条来指示拷贝的进度。
删除文件的函数是DeleteFile仅有的参数是要删除文件的名称。
如果应用程序试图删除不存在的文件DeleteFile将执行失败。
如果目标文件是只读的函数也会执行失败出错代码为ERROR_ACCESS_DENIED。
为了删除只读文件先要去掉其只读属性。
DeleteFile函数可以标识一个文件为“关闭时删除”。
因此直到最后一个到此文件的句柄关闭之后文件才会被删除。
下面的自定义函数RecursiveDelete示例了如何删除指定。
用DeleteFile函数删除的文件不会被放到回收站它们将永远丢失所以请小心使用RecursiveDelete函数。
移动文件的函数是MoveFile和MoveFileEx函数。
它们的主要功能都是用来移动一个存在的文件或目录。
MoveFile函数用法如下。
函数并不马上执行而是在操作系统下一此重新启动时才移动文件。
在AUTOCHK执行之后系统立即移动文件这是在创建任何分页文件之前进行的。
因此这个值使函数能够删除上一次运行时使用的分页文件。
只有拥有管理员权限的用户才可以使用这个值
如果指定了MOVEFILE_DELAY_UNTIL_REBOOT标记lpNewFileName参数可以指定为NULL这种情况下当系统下一次启动时操作系统会删除lpExistingFileName参数指定的文件。
PE文件格式是任何可执行模块或者DLL的文件格式PE文件以64字节的DOS文件头IMAGE_DOS_HEADER结构开始之后是一小段DOS程序然后是248字节的NT文件头IMAGE_NT_HEADERS结构。
NT文件头的偏移地址由IMAGE_DOS_HEADER结构的e_lfanew成员给出。
检查文件是不是有效PE文件的一个方法是检查IMAGE_DOS_HEADER和IMAGE_NT_HEADERS结构是否有效。
IMAGE_DOS_HEADER结构定义如下。
为了编程方便Windows为DOS文件标记和PE文件标记都定义了宏标识。
1检验文件头部第一个字的值是否等于IMAGE_DOS_SIGNATURE是则说明DOS
2一旦证明文件的DOS头有效后就可用e_lfanew来定位PE头了。
3比较PE头的第一个字是否等于IMAGE_NT_SIGNATURE。
如果这个值也匹配那么就认为该文件是一个有效的PE文件。
下面是验证PE文件有效性的代码在配套光盘的08ValidPE工程下。
::CreateFile(dlg.GetFileName(),
INVALID_HANDLE_VALUE){MessageBox(NULL,
定义PE文件中的DOS头和NT头IMAGE_DOS_HEADER
sizeof(dosHeader)){if(dosHeader.e_magic
定位NT头if(::SetFilePointer(hFile,
sizeof(ntHeader)){if(ntHeader.Signature
MB_OK);::CloseHandle(hFile);return
}上述代码简单明确先利用Windows定义的宏IMAGE_DOS_SIGNATURE判断DOS头比较DOS头的e_magic字段再通过DOS头的e_lfanew字段定位到NT头最后检查NT头的Signature字段是不是IMAGE_NT_SIGNATURE即“PE\0\0”。
CFile是一个相当简单的封装了一部分文件I/O处理函数的类。
它的成员函数用于打开和关闭文件、读写文件数据、删除和重命名文件、取得文件信息。
它的公开成员变量m_hFile保存了与CFile对象关联的文件的文件句柄。
一个受保护的CString类型的成员变量m_strFileName保存了文件的名称。
成员函数GetFilePath、GetFileName和GetFileTitle能够用来提取整个或者部分文件名。
比如如果完整的文件名是“C:\MyWork\File.txt”GetFilePath返回整个字符串GetFileName返回“File.txt”GetFileTitle返回“File”。
但是详述这些函数就会忽略CFile类的特色这就是用来写数据到磁盘和从磁盘读数据的函数。
下面简单介绍CFile类用法。
1构造一个未初始化的CFile对象调用CFile::Open函数。
下面的部分代码使用这个技术以读写权限打开一个名称为File.txt的文件。
}CFile::Open函数的返回值是BOOL类型的变量。
如果打开文件出错还想进一步了解出错的原因可以创建一个CFileException对象传递它的地址到Open函数的第3个参数。
如果打开失败CFile::Open函数会使用描述失败原因的信息初始化一个CFileException对象。
ReportError成员函数基于这个信息显示一个出错对话框。
可以通过检查CFileException类的公有成员m_cause找到导致这个错误的原因。
2使用CFile类的构造函数。
可以将创建文件对象和打开文件合并成一步如下面代码所示。
如果文件不能被打开CFile的构造函数会抛出一个CFileException异常。
因此使用CFile::CFile函数打开文件的代码通常使用try和catch块来捕获错误。
删除MFC抛出的异常是程序写作者的责任所以在程序中处理完异常之后要调用异常对象的Delete函数。
为了创建一个文件而不是打开一个存在的文件要在CFile::Open或者CFile构造函数的第二个参数中包含上CFile::modeCreate标记如下代码所示。
如果以这种方式创建的文件存在它的长度会被截为0。
为了在文件不存在时创建它存在的时候仅打开而不截去应再包含上CFile::modeNoTruncate标记如下面代码所示。
默认情况下由CFile::Open或CFile::CFile打开的文件使用的是独占模式即CreateFile
API中的第3个参数dwShareMode被设为了0。
如果需要在打开文件时也可以指定一个共享模式以明确同意其他访问此文件的操作。
这里是4个可以选择的共享模式
拒绝其他代码对这个文件进行读和写操作默认另外还可以指定下面3个对象访问类型中的一个
常用的做法是允许其他程序以只读方式打开文件但是拒绝它们写入数据。
如果在上面的代码执行之前文件已经以可写的方式打开了这个调用将会失败CFile类会抛出CFileException异常异常对象的m_cause成员等于CFileException::sharingViolation。
API关闭应用程序打开的文件对象句柄。
如果句柄没有关闭类的析构函数也会调用Close函数关闭它。
显式调用Close函数一般都是为了关闭当前打开的文件以便使用同样的CFile对象打开另一个文件。
CFile类中从文件中读取数据的成员函数是Read。
例如下面的代码申请了一块4KB大小的文件I/O缓冲区每次从文件读取4KB大小的数据。
文件中未读取的字节数保存在dwBytesRemaining变量里此变量由CFile::GetLength返回的文件长度初始化。
每次调用Read之后从文件中读取的字节数nBytesRead会从dwBytesRemaining变量里减去。
直到dwBytesRemaining为0整个while循环才结束。
CFile类还提供了Write成员函数向文件写入数据Seek成员函数移动文件指针它们都和相关API一一对应。
可以通过跟踪程序的执行来查看这些函数的实现代码。
作为专业的SEO优化服务提供商,我们致力于通过科学、系统的搜索引擎优化策略,帮助企业在百度、Google等搜索引擎中获得更高的排名和流量。我们的服务涵盖网站结构优化、内容优化、技术SEO和链接建设等多个维度。
| 服务项目 | 基础套餐 | 标准套餐 | 高级定制 |
|---|---|---|---|
| 关键词优化数量 | 10-20个核心词 | 30-50个核心词+长尾词 | 80-150个全方位覆盖 |
| 内容优化 | 基础页面优化 | 全站内容优化+每月5篇原创 | 个性化内容策略+每月15篇原创 |
| 技术SEO | 基本技术检查 | 全面技术优化+移动适配 | 深度技术重构+性能优化 |
| 外链建设 | 每月5-10条 | 每月20-30条高质量外链 | 每月50+条多渠道外链 |
| 数据报告 | 月度基础报告 | 双周详细报告+分析 | 每周深度报告+策略调整 |
| 效果保障 | 3-6个月见效 | 2-4个月见效 | 1-3个月快速见效 |
我们的SEO优化服务遵循科学严谨的流程,确保每一步都基于数据分析和行业最佳实践:
全面检测网站技术问题、内容质量、竞争对手情况,制定个性化优化方案。
基于用户搜索意图和商业目标,制定全面的关键词矩阵和布局策略。
解决网站技术问题,优化网站结构,提升页面速度和移动端体验。
创作高质量原创内容,优化现有页面,建立内容更新机制。
获取高质量外部链接,建立品牌在线影响力,提升网站权威度。
持续监控排名、流量和转化数据,根据效果调整优化策略。
基于我们服务的客户数据统计,平均优化效果如下:
我们坚信,真正的SEO优化不仅仅是追求排名,而是通过提供优质内容、优化用户体验、建立网站权威,最终实现可持续的业务增长。我们的目标是与客户建立长期合作关系,共同成长。
Demand feedback