当前位置: 首页 > news >正文

万网域名申请网站长沙网站seo外包

万网域名申请网站,长沙网站seo外包,重庆大足网站制作公司,自己做装修网站需要多少钱文件的输入输出(I/O)服务是操作系统的重要部分。Windows提供了一类API函数来读、写和管理磁盘文件。MFC将这些函数转化为一个面向对象的类——CFile,它允许将文件视为可以由CFile成员函数操作的对象,如Read和Write等。CFile类实现…

文件的输入输出(I/O)服务是操作系统的重要部分。Windows提供了一类API函数来读、写和管理磁盘文件。MFC将这些函数转化为一个面向对象的类——CFile,它允许将文件视为可以由CFile成员函数操作的对象,如Read和Write等。CFile类实现了程序开发者执行底层文件I/O需要的大部分功能。

并不是在任何时候使用CFile类都是方便的,特别是要与底层设备(如COM口、设备驱动)进行交互的时候,所以本节主要讨论管理文件的API函数。事实上,了解这些函数之后,自然就会使用CFile类了。

8.1.1 创建和读写文件

使用API函数读写文件时,首先要使用CreateFile函数创建文件对象(即打开文件),调用成功会返回文件句柄;然后以此句柄为参数调用ReadFile和WriteFile函数,进行实际的读写操作;最后调用CloseHandle函数关闭不再使用的文件对象句柄。

1.打开和关闭文件
CreateFile是一个功能相当强大的函数,Windows下的底层设备差不多都是由它打开的。它可以创建或打开文件、目录、物理磁盘、控制台缓冲区、邮槽和管道等。调用成功后,函数返回能够用来访问此对象的句柄,其原型如下。

HANDLE CreateFile (  LPCTSTR lpFileName,   // 要创建或打开的对象的名称  DWORD dwDesiredAccess,  // 文件的存取方式  DWORD dwShareMode,  // 共享属性 LPSECURITY_ATTRIBUTES lpSecurityAttributes, // 安全属性  DWORD dwCreationDisposition, // 文件存在或不存在时系统采取的行动  DWORD dwFlagsAndAttributes, // 新文件的属性  HANDLE hTemplateFile // 一个文件模板的句柄 
); 

各参数含义如下。
(1)lpFileName参数是要创建或打开的对象的名称。如果打开文件,直接在这里指定文件名称即可;如果操作对象是第一个串口,则要指定“COM1”为文件名,然后就可以像操作文件一样操作串口了;如果要打开本地电脑上的一个服务,要以“"\\.\服务名称"”为文件名,其中的“.”代表本地机器;也可以使用CreateFile打开网络中其他主机上的文件,此时的文件名应该是“\\主机名\共享目录名\文件名”。
(2)dwDesiredAcces参数是访问方式,它指定了要对打开的对象进行何种操作。指定GENERIC_READ标志表示以只读方式打开;指定GENERIC_WRITE标志表示以只写方式打开;指定这两个值的组合,表示要同时对打开的对象进行读写操作。
(3)dwShareMode参数指定了文件对象的共享模式,表示文件打开后是否允许其他代码以某种方式再次打开这个文件,它可以是下列值的一个组合:

0                   不允许文件再被打开 C语言中的fopen函数就是这样打开文件的 
FILE_SHARE_DELETE   允许以后的程序代码对文件删除文件(Win98系列的系统不支持这 个标志) 
FILE_SHARE_READ     允许以后的程序代码以读方式打开文件
FILE_SHARE_WRITE    允许以后的程序代码以写方式打开文件

(4)dwCreationDisposition参数指定了当文件已存在或者不存在时系统采取的动作。在这里设置不同的标志就可以决定究竟是要打开文件,还是要创建文件。参数的可能取值如下:

CREATE_ALWAYS       创建新文件。如果文件存在,函数会覆盖这个文件,清除存在的属性 
CREATE_NEW          创建新文件。如果文件存在,函数执行失败 
OPEN_ALWAYS         如果文件已经存在,就打开它,不存在则创建新文件 
OPEN_EXISTING       打开存在的文件。如果文件不存在,函数执行失败 
TRUNCATE_EXISTING   打开文件并将文件截断为零,当文件不存在时函数执行失败 

(5)dwFlagsAndAttributes参数用来指定新建文件的属性和标志。文件属性可以是下面这些值的组合:

FILE_ATTRIBUTE_ARCHIVE    标记归档属性 
FILE_ATTRIBUTE_HIDDEN     标记隐藏属性
FILE_ATTRIBUTE_READONLY   标记只读属性 
FILE_ATTRIBUTE_READONLY   标记系统属性
FILE_ATTRIBUTE_TEMPORARY  临时文件。操作系统会尽量把所有文件的内容保持在内 存中以加快存取速度。使用完后要尽快将它删除

此参数还可同时指定对文件的操作方式,下面是一些比较常用的方式:

FILE_FLAG_DELETE_ON_CLOSE  文件关闭后系统立即自动将它删除
FILE_FLAG_OVERLAPPED       使用异步读写文件的方式 
FILE_FLAG_WRITE_THROUGH    系统不会对文件使用缓存,文件的任何改变都会被系统 立即写入硬盘

(6)hTemplateFile参数指定了一个文件模板句柄。系统会复制该文件模板的所有属性到当前创建的文件中。Windows 98系列的操作系统不支持它,必须设为NULL。

打开或创建文件成功时,函数返回文件句柄,失败时返回INVALID_HANDLE_VALUE(-1)。如果想再详细了解失败的原因,可以继续调用GetLastError函数。

用不同的参数组合调用CreateFile函数可以完成不同的功能,例如,下面的代码为读取数据打开了一个存在的文件。

HANDLE hFile;  
hFile = CreateFile("myfile.txt", // 要创建的文件  GENERIC_WRITE, // 要写这个文件  0, // 不共享  NULL, // 默认安全属性  CREATE_ALWAYS, // 如果存在就覆盖  FILE_ATTRIBUTE_NORMAL, // 普通文件  NULL); // 没有模板  if(hFile == INVALID_HANDLE_VALUE)  { ……// 不能够打开文件 } 

要关闭打开的文件,直接以CreateFile返回的文件句柄调用CloseHandle函数即可。

2.移动文件指针
系统为每个打开的文件维护一个文件指针,指定对文件的下一个读写操作从什么位置开始。随着数据的读出或写入,文件指针也随之移动。当文件刚被打开时,文件指针处于文件的头部。有时候需要随机读取文件内容,这就需要先调整文件指针,SetFilePointer函数提供了这个功能,原型如下。

DWORD SetFilePointer (  HANDLE hFile, // 文件句柄  LONG lDistanceToMove, // 要移动的距离  PLONG lpDistanceToMoveHigh, // 移动距离的高32位,一般设置为NULL  DWORD dwMoveMethod // 移动的模式  
); 

dwMoveMethod参数指明了从什么地方开始移动,可以是下面的一个值:

FILE_BEGIN    开始移动位置为0,即从文件头部开始移动
FILE_CURRENT  开始移动位置是文件指针的当前值 
FILE_END      开始移动位置是文件的结尾,即从文件尾开始移动

函数执行失败返回-1,否则返回新的文件指针的位置。

文件指针也可以移动到所有数据的后面,比如现在文件的长度是100 KB,但还是可以成功的将文件指针移动到1000 KB的位置。这样做可以达到扩展文件长度的目的。

SetEndOfFile函数可以截断或者扩展文件。该函数移动指定文件的结束标志(end-of-file,EOF)到文件指针指向的位置。如果文件扩展,旧的EOF位置和新的EOF位置间的内容是未定义的。SetEndOfFile函数的用法如下。

BOOL SetEndOfFile(HANDLE hFile); 

截断或者扩展文件时,要首先调用SetFilePointer移动文件指针,然后再调用SetFilePointer函数设置新的文件指针位置为EOF。

3.读写文件
读写文件的函数是ReadFile和WriteFile,这两个函数既可以同步读写文件,又可以异步读写文件。而函数ReadFileEx和WriteFileEx只能异步读写文件。

从文件读取数据的函数是ReadFile,向文件写入数据的函数是WriteFile,操作的开始位置由文件指针指定。这两个函数的原型如下。

BOOL ReadFile(  
HANDLE hFile, // 文件句柄  
LPVOID lpBuffer, // 指向一个缓冲区,函数会将读出的数据返回到这里  
DWORD nNumberOfBytesToRead, // 要求读入的字节数  
LPDWORD lpNumberOfBytesRead, // 指向一个DWORD类型的变量,  // 用于返回实际读入的字节数  
LPOVERLAPPED lpOverlapped // 以便设为NULL 
); 
BOOL WriteFile (hFile, lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten, lpOverlapped); 

当用WriteFile写文件时,写入的数据通常被Windows暂时保存在内部的高速缓存中,等合适的时候再一并写入磁盘。如果一定要保证所有的数据都已经被传送,可以强制使用FlushFileBuffers函数来清空数据缓冲区,函数的惟一参数是要操作的文件句柄。

BOOL FlushFileBuffers (HANDLE hFile ); 

4.锁定文件
当对文件数据的一致性要求较高时,为了防止程序在写入的过程中其他进程刚好在读取写入区域的内容,可以对已打开文件的某个部分进行加锁,这就可以防止其他进程对该区域进行读写。加锁和解锁的函数是LockFile和UnlockFile,它们的原形如下。

BOOL LockFile(  HANDLE hFile, // 文件句柄  DWORD dwFileOffsetLow, // 加锁的开始位置  DWORD dwFileOffsetHigh,  DWORD nNumberOfBytesToLockLow, // 加锁的区域的大小  DWORD nNumberOfBytesToLockHigh  
); 
UnlockFile ( hFile, dwFileOffsetLow, dwFileOffsetHigh,  nNumberOfBytesToUnlockLow, nNumberOfBytesToUnlockHigh); 

dwFileOffsetLow和dwFileOffsetHigh参数组合起来指定了加锁区域的开始位置,nNumberOfBytesToLockLow和nNumberOfBytesToLockHigh参数组合起来指定了加锁区域的大小。这两个参数都指定了一个64位的值,在Win32中,只使用32位就够了。

如果加锁文件的进程终止,或者文件关闭时还未解锁,操作系统会自动解除对文件的锁定。但是,操作系统解锁文件花费的时间取决于当前可用的系统资源。因此,进程终止时最好显式地解锁所有已锁定的文件,以免造成这些文件无法访问。

8.1.2 获取文件信息

1.获取文件类型
Windows下的许多对象都称之为文件,如果想知道一个文件句柄究竟对应什么对象,可以使用GetFileType函数,原型如下。

DWORD GetFileType(HANDLE hFile); 

函数的返回值说明了文件类型,可以是下面的一个值:

FILE_TYPE_CHAR     指定文件是字符文件,通常是LPT设备或控制台 
FILE_TYPE_DISK     指定文件是磁盘文件 
FILE_TYPE_PIPE     指定文件是套节字,一个命名的或未命名的管道 
FILE_TYPE_UNKNOWN  不能识别指定文件,或者函数调用失败 

2.获取文件大小
如果确定操作的对象是磁盘文件,还可以使用GetFileSize函数取得这个文件的长度。

DWORD GetFileSize(  HANDLE hFile, // 文件句柄  LPDWORD lpFileSizeHigh // 用于返回文件长度的高字。可以指定这个参数为NULL 
); 

函数执行成功将返回文件大小的低双字,如果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来响应成功。

3.获取文件属性
如果要查看文件或者目录的属性,可以使用GetFileAttributes函数,它会返回一系列FAT风格的属性信息。

DWORD GetFileAttributes(LPCTSTR lpFileName); // lpFileName指定了文件或者目录的名称 

函数执行成功,返回值包含了指定文件或目录的属性信息,可以是下列取值的组合:

FILE_ATTRIBUTE_ARCHIVE     文件包含归档属性 
FILE_ATTRIBUTE_COMPRESSED  文件和目录被压缩 
FILE_ATTRIBUTE_DIRECTORY   这是一个目录 
FILE_ATTRIBUTE_HIDDEN      文件包含隐含属性
FILE_ATTRIBUTE_NORMAL      文件没有其他属性 
FILE_ATTRIBUTE_READONLY    文件包含只读属性
FILE_ATTRIBUTE_SYSTEM      文件包含系统属性
FILE_ATTRIBUTE_TEMPORARYT  文件是一个临时文件 

这些属性对目录也同样适用。INVALID_FILE_ATTRIBUTES(0xFFFFFFFF)是函数执行失败后的返回值。

下面是快速检查某个文件或目录是否存在的自定义函数,可以将它用在自己的工程中。

BOOL FileExists(LPCTSTR lpszFileName, BOOL bIsDirCheck) 
{ // 试图取得文件的属性  DWORD dwAttributes = GetFileAttributes(lpszFileName);  if(dwAttributes == 0xFFFFFFFF)  return FALSE;  if ((dwAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY)  { if (bIsDirCheck)  return TRUE; else  return FALSE;  }  else  { if (!bIsDirCheck)  return TRUE; else  return FALSE;  } 
} 

第2个参数bIsDirCheck指定要检查的对象是目录还是文件。

与GetFileAttributes相对应的函数是SetFileAttributes,这个函数用来设置文件属性。

BOOL SetFileAttributes(  LPCTSTR lpFileName, // 目标文件名称  DWORD dwFileAttributes // 要设置的属性值 
); 

8.1.3 常用文件操作

1.拷贝文件
拷贝文件的函数是CopyFile和CopyFileEx,其作用都是复制一个存在的文件到一个新文件中。CopyFile函数的用法如下。

BOOL CopyFile(  LPCTSTR lpExistingFileName, // 指定已存在的文件的名称  LPCTSTR lpNewFileName, // 指定新文件的名称  BOOL bFailIfExists // 如果指定的新文件存在是否按出错处理 
); 

CopyFileEx函数的附加功能是允许指定一个回调函数,在拷贝过程中,函数每拷贝完一部分数据,就会调用回调函数。用户在回调函数中可以指定是否停止拷贝,还可以显示进度条来指示拷贝的进度。

2.删除文件
删除文件的函数是DeleteFile,仅有的参数是要删除文件的名称。

BOOL DeleteFile(LPCTSTR lpFileName); 

如果应用程序试图删除不存在的文件,DeleteFile将执行失败。如果目标文件是只读的,函数也会执行失败,出错代码为ERROR_ACCESS_DENIED。为了删除只读文件,先要去掉其只读属性。

DeleteFile函数可以标识一个文件为“关闭时删除”。因此,直到最后一个到此文件的句柄关闭之后,文件才会被删除。

下面的自定义函数RecursiveDelete示例了如何删除指定目录下的所有文件和子目录。

void RecursiveDelete(CString szPath) 
{ CFileFind ff; // MFC将查找文件的API封装到了CFileFind类 读者可参考下面的框架使用这个类  CString strPath = szPath;  // 说明要查找此目录下的所有文件  if(strPath.Right(1) != "\\")  strPath += "\\"; strPath += "*.*";  BOOL bRet;  if(ff.FindFile(strPath))  { do  { bRet = ff.FindNextFile();  if(ff.IsDots()) // 目录为“.”或者“..”?  continue;  strPath = ff.GetFilePath();  if(!ff.IsDirectory())  { // 删除此文件  ::SetFileAttributes(strPath, FILE_ATTRIBUTE_NORMAL);  ::DeleteFile(strPath);  }   else  { // 递归调用  RecursiveDelete(strPath);  // 删除此目录(RemoveDirectory只能删除空目录)  ::SetFileAttributes(strPath, FILE_ATTRIBUTE_NORMAL);  ::RemoveDirectory(strPath);  }  }  while(bRet);  } 
} 

用DeleteFile函数删除的文件不会被放到回收站,它们将永远丢失,所以请小心使用RecursiveDelete函数。

3.移动文件
移动文件的函数是MoveFile和MoveFileEx函数。它们的主要功能都是用来移动一个存在的文件或目录。MoveFile函数用法如下。

BOOL MoveFile(  LPCTSTR lpExistingFileName, // 存在的文件或目录  LPCTSTR lpNewFileName // 新的文件或目录 
); 

当需要指定如何移动文件时,请使用MoveFileEx函数。

BOOL MoveFileEx(LPCTSTR lpExistingFileName, LPCTSTR lpNewFileName, DWORD dwFlags);

dwFlags参数可以是下列值的组合:

MOVEFILE_DELAY_UNTIL_REBOOT   函数并不马上执行,而是在操作系统下一此重新启动时才移动文件。在AUTOCHK执行之后,系统立即移动文件,这是在创建任何分页文件之前进行的。因此,这个值使函数能够删除上一次运行时使用的分页文件。只有拥有管理员权限的用户才可以使用这个值 
MOVEFILE_REPLACE_EXISTING     如果目标文件已存在的话,就将它替换掉
MOVEFILE_WRITE_THROUGH        直到文件实际从磁盘移除之后函数才返回 

如果指定了MOVEFILE_DELAY_UNTIL_REBOOT标记,lpNewFileName参数可以指定为NULL,这种情况下,当系统下一次启动时,操作系统会删除lpExistingFileName参数指定的文件。

8.1.4 检查PE文件有效性的例子

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结构定义如下。

typedef struct _IMAGE_DOS_HEADER 
{  WORD e_magic; // DOS可执行文件标记,为“MZ”。依此识别DOS头是否有效  ... // 其他成员,没什么用途  LONG e_lfanew; // IMAGE_NT_HEADERS结构的地址  
} IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER; 

IMAGE_NT_HEADERS结构定义如下。

typedef struct _IMAGE_NT_HEADERS 
{  DWORD Signature; // PE文件标识,为“PE\0\0”。依此识别NT文件头是否有效  IMAGE_FILE_HEADER FileHeader;  IMAGE_OPTIONAL_HEADER OptionalHeader;  
} IMAGE_NT_HEADERS, 

为了编程方便,Windows为DOS文件标记和PE文件标记都定义了宏标识。

#define IMAGE_DOS_SIGNATURE   0x5A4D // MZ 
#define IMAGE_NT_SIGNATURE    0x00004550 // PE00 

检查文件是否为PE文件的步骤如下:
(1)检验文件头部第一个字的值是否等于IMAGE_DOS_SIGNATURE,是则说明DOS MZ头有效。
(2)一旦证明文件的DOS头有效后,就可用e_lfanew来定位PE头了。
(3)比较PE头的第一个字是否等于IMAGE_NT_SIGNATURE。如果这个值也匹配,那么就认为该文件是一个有效的PE文件。

下面是验证PE文件有效性的代码,在配套光盘的08ValidPE工程下。

// ValidPE.cpp文件#include <afxdlgs.h>
#include "ValidPE.h"CMyApp theApp;BOOL CMyApp::InitInstance()
{// 弹出选色文件对话框CFileDialog dlg(TRUE);if(dlg.DoModal() != IDOK)return FALSE;// 打开检查的文件HANDLE hFile = ::CreateFile(dlg.GetFileName(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);if(hFile == INVALID_HANDLE_VALUE){MessageBox(NULL, "无效文件!", "ValidPE", MB_OK);}// 定义PE文件中的DOS头和NT头IMAGE_DOS_HEADER dosHeader;IMAGE_NT_HEADERS32 ntHeader;	// 验证过程BOOL bValid = FALSE;DWORD dwRead;// 读取DOS头::ReadFile(hFile, &dosHeader, sizeof(dosHeader), &dwRead, NULL);if(dwRead == sizeof(dosHeader)){if(dosHeader.e_magic == IMAGE_DOS_SIGNATURE) // 是不是有效的DOS头?{// 定位NT头if(::SetFilePointer(hFile, dosHeader.e_lfanew, NULL, FILE_BEGIN) != -1){// 读取NT头::ReadFile(hFile, &ntHeader, sizeof(ntHeader), &dwRead, NULL);if(dwRead == sizeof(ntHeader)){if(ntHeader.Signature == IMAGE_NT_SIGNATURE)	// 是不是有效的NT头bValid = TRUE;}}}}// 显示结果if(bValid)MessageBox(NULL, "是一个PE格式的文件!", "ValidPE", MB_OK);elseMessageBox(NULL, "不是一个PE格式的文件!", "ValidPE", MB_OK);::CloseHandle(hFile);return FALSE;
}

在这里插入图片描述
上述代码简单明确,先利用Windows定义的宏IMAGE_DOS_SIGNATURE判断DOS头,比较DOS头的e_magic字段;再通过DOS头的e_lfanew字段定位到NT头;最后检查NT头的Signature字段是不是IMAGE_NT_SIGNATURE(即“PE\0\0”)。

8.1.5 MFC的支持(CFile类)

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类打开文件有两种方法。

(1)构造一个未初始化的CFile对象,调用CFile::Open函数。下面的部分代码使用这个技术以读写权限打开一个名称为File.txt的文件。

CFile file; 
if(file.Open(_T ("File.txt"), CFile::modeReadWrite)) 
{ // 打开文件成功
}

CFile::Open函数的返回值是BOOL类型的变量。如果打开文件出错,还想进一步了解出错的原因,可以创建一个CFileException对象,传递它的地址到Open函数的第3个参数。

CFile file; 
CFileException e; 
if (file.Open(_T ("File.txt"), CFile::modeReadWrite, &e)) 
{ // 打开文件成功
} 
else 
{ // 打开文件失败,告诉用户原因  e.ReportError(); 
} 

如果打开失败,CFile::Open函数会使用描述失败原因的信息初始化一个CFileException对象。ReportError成员函数基于这个信息显示一个出错对话框。可以通过检查CFileException类的公有成员m_cause找到导致这个错误的原因。

(2)使用CFile类的构造函数。可以将创建文件对象和打开文件合并成一步,如下面代码所示。

CFile file(_T ("File.txt"), CFile::modeReadWrite); 

如果文件不能被打开,CFile的构造函数会抛出一个CFileException异常。因此,使用CFile::CFile函数打开文件的代码通常使用try和catch块来捕获错误。

try 
{ CFile file(_T ("File.txt"), CFile::modeReadWrite); 
} 
catch(CFileException* e) 
{ // 出错了!  e->ReportError();  e->Delete(); 
} 

删除MFC抛出的异常是程序写作者的责任,所以在程序中处理完异常之后要调用异常对象的Delete函数。

为了创建一个文件而不是打开一个存在的文件,要在CFile::Open或者CFile构造函数的第二个参数中包含上CFile::modeCreate标记,如下代码所示。

CFile file(_T("File.txt"), CFile::modeReadWrite | CFile::modeCreate); 

如果以这种方式创建的文件存在,它的长度会被截为0。为了在文件不存在时创建它,存在的时候仅打开而不截去,应再包含上CFile::modeNoTruncate标记,如下面代码所示。

CFile file(_T("File.txt"), CFile::modeReadWrite | CFile::modeCreate | CFile::modeNoTruncate); 

默认情况下,由CFile::Open或CFile::CFile打开的文件使用的是独占模式,即CreateFile API中的第3个参数dwShareMode被设为了0。如果需要,在打开文件时也可以指定一个共享模式,以明确同意其他访问此文件的操作。这里是4个可以选择的共享模式:

CFile::shareDenyNone   不独占这个文件 
CFile::shareDenyRead   拒绝其他代码对这个文件进行读操作 
CFile::shareDenyWrite  拒绝其他代码对这个文件进行写操作
CFile::shareExclusive  拒绝其他代码对这个文件进行读和写操作(默认)

另外,还可以指定下面3个对象访问类型中的一个:

CFile::modeReadWrite  请求读写访问 
CFile::modeRead       仅请求读访问 
CFile::modeWrite      仅请求写访问 

常用的做法是允许其他程序以只读方式打开文件,但是拒绝它们写入数据。

CFile file(_T("File.txt"), CFile::modeReadWrite | CFile::modeCreate | CFile::modeNoTruncate); 

如果在上面的代码执行之前,文件已经以可写的方式打开了,这个调用将会失败,CFile类会抛出CFileException异常,异常对象的m_cause成员等于CFileException::sharingViolation。

CFile类的成员函数Close会调用CloseHandle API关闭应用程序打开的文件对象句柄。如果句柄没有关闭,类的析构函数也会调用Close函数关闭它。显式调用Close函数一般都是为了关闭当前打开的文件,以便使用同样的CFile对象打开另一个文件。

2.读写文件
CFile类中从文件中读取数据的成员函数是Read。例如,下面的代码申请了一块4KB大小的文件I/O缓冲区,每次从文件读取4KB大小的数据。

BYTE buffer[4096]; 
CFile file (_T("File.txt"), CFile::modeRead); 
DWORD dwBytesRemaining = file.GetLength(); 
while(dwBytesRemaining) 
{ UINT nBytesRead = file.Read(buffer, sizeof(buffer));  dwBytesRemaining -= nBytesRead; 
} 

文件中未读取的字节数保存在dwBytesRemaining变量里,此变量由CFile::GetLength返回的文件长度初始化。每次调用Read之后,从文件中读取的字节数(nBytesRead)会从dwBytesRemaining变量里减去。直到dwBytesRemaining为0整个while循环才结束。

CFile类还提供了Write成员函数向文件写入数据,Seek成员函数移动文件指针,它们都和相关API一一对应。可以通过跟踪程序的执行来查看这些函数的实现代码。

http://www.hotlads.com/news/1977.html

相关文章:

  • 网站做进一步优化如何做推广和引流
  • 什么公司做网站好网络平台推广方案
  • 全媒体广告策划营销seo培训教程
  • 沈阳做网站的地方百度网站介绍
  • 网络工程师工作好找吗什么建站程序最利于seo
  • 百度做公司网站多少钱营销传播服务
  • 营销网站优化seo网络营销是什么课程
  • 丰都网站建设哪家好网络公司经营范围
  • 汽车类网站百度查重免费
  • 南宁网站建设 超薄网络网络竞价托管公司
  • 动态网站开发技术包括企业管理培训班
  • 青岛建设厅官方网站上海专业做网站
  • 宝塔做网站可以用什么端口优秀网站网页设计
  • 涞源县住房和城乡建设局网站上海网站seo公司
  • 做网站用什么字体字号什么是seo推广
  • 广州网站建设推荐乐云seo关键词排名推广软件
  • 北京手机专业网站建设公司aso推广优化
  • 描写做网站专业的句子指数型基金是什么意思
  • 商城网站开发报价方案抚顺seo
  • 英文网站建设 招标办理培训机构需要具备的条件
  • 苹果cms网站广告怎么做2021拉新推广佣金排行榜
  • 写作的网站有哪些网络营销案例成功案例
  • 室内设计师联盟网系统优化的意义
  • 定制网站前准备网络广告的概念
  • 宁波建设网站公司推荐产品推广方式都有哪些
  • 邯郸网站建设哪家专业seo的优化技巧有哪些
  • app制作网站制作完快手秒赞秒评网站推广
  • 龙岗区网站建设建设网站公司
  • 网站防止被采集广州营销课程培训班
  • 芜湖网站建设公司江苏网站推广