当我们对文件进行读写操作的时候,我们经常会调用ReadFile和WriteFile这两个API,但是如果我们的文件较大,几百兆甚至几G且需要时常修改值B的时候,这时那两个函数可能就不大好了,这时微软提供了另外一种方法--文件映射,来使我们进行文件操作。
首先,我们先介绍几个API,第一个就是CreateFileMapping,声明如下:
HANDLE CreateFileMapping(
HANDLE hFile, // 文件句柄
LPSECURITY_ATTRIBUTES lpAttributes, // 安全属性,一般为NULL
DWORD flProtect, // 保护属性
DWORD dwMaximumSizeHigh, // 内存映射文件的大小,高32位
DWORD dwMaximumSizeLow, // 内存映射文件的大小,低32位
LPCTSTR lpName // 指定映射对象的名称,一般不需要,给NULL就行
);
第二个API是MapViewOfFile,声明如下:
LPVOID MapViewOfFile(
HANDLE hFileMappingObject, // 文件映射对象的句柄
DWORD dwDesiredAccess, // 访问的模式
DWORD dwFileOffsetHigh, // 文件的偏移量,高32位
DWORD dwFileOffsetLow, // 文件的偏移量,低32位
SIZE_T dwNumberOfBytesToMap // 映射的字节数
);
第三个是FlushViewOfFile,声明如下:
BOOL FlushViewOfFile(
LPCVOID lpBaseAddress, // 开始的地址,由上一个API的返回值一样
SIZE_T dwNumberOfBytesToFlush // 要刷新的字节数
);
第四个是UnmapViewOfFile,声明如下:
BOOL UnmapViewOfFile(
LPCVOID lpBaseAddress // 开始的地址,由MapViewOfFile返回值一样
);
附上以上代码的例子:
#include <windows.h>
int _tmain(int argc, _TCHAR* argv[])
{
//打开文件
HANDLE hFile = CreateFile(L"test.txt", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, NULL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
printf("open file failed!");
return -1;
}
//获取文件的大小
DWORD dwSize = GetFileSize(hFile, 0);
//创建文件映射对象
HANDLE hMap = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 0, 0);
//映射到具体的内存
LPBYTE pBuf = (LPBYTE)MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, 10); //虽然这里只映射10个字节,但是系统却并不只是映射10个字节,系统会做一个跟硬盘的一个扇区大小做对齐,一般来说,一个扇区为512个字节,若不够一个扇区,则默认映射一个扇区,总之,映射的大小为扇区大小的整数倍
//将第三个字节和第四个字节改为1和2
pBuf[3] = 0x31;
pBuf[4] = 0x32;
//将更新的内容刷新到文件中
FlushViewOfFile(pBuf, dwSize);
//释放内存区域
UnmapViewOfFile(pBuf);
CloseHandle(hMap);
CloseHandle(hFile);
return 0;
}