内存映射是为了方便多个进程间的共同开发从而共享一段内存,但是,它还有一个其他功能,那就是修改文件
在内存映射之前,首先我们需要用 CreatFile()来打开文件,如果我们需要对文件进行修改的话,第二个关键函数必须设置;
hFile=::CreateFile(lpFilename,GENERIC_WRITE|GENERIC_READ ,NULL,NULL,OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,0);
接下来就是获取文件大小,if ( INVALID_FILE_SIZE == ( mapp.dwSize=GetFileSize(hFile,NULL)) ) 如果相等就是获取错误了。(获取文件大小很关键,下面我会提到)
然后就是经典的CreateFileMapping()来映射文件到内存了, 这个函数共有6个参数,楼主在之前修改文件的时候是读取文件,然后对文件字符串加密,但是加密后的体积比原文件大,这样的话我在写入的时候总是出现问题,后来仔细看了MSDN才发现,猫腻就在这个函数,它的第五个跟第六个函数告诉我们我们要映射文件的高32位的最大值,与低32位的最小值,如果两个都为零的话,它默认映射的大小就是原文件的大小,所以你在试图修改它的映射文件并把它映射回去的时候,会出现比原文件大的情况,这样就出现问题了,所有,我们在映射文件到到内存之前,最好求出我们修改后的文件大小,给CreateFileMapping();
最后就是获取我们映射到内存的基地址了,
ImageBase=::MapViewOfFile(hMapping,FILE_MAP_WRITE,0,0,0);
还有 ,别忘了关闭句柄,CloseHandle
上例子一个,与君共勉
// 映射文件到内存 输入文件名,返回映射内存的基址
LPVOID LoadFileR(LPTSTR lpFilename, DWORD dwSize)
{
HANDLE hFile;
HANDLE hMapping;
LPVOID ImageBase;
hFile=::CreateFile(lpFilename,GENERIC_WRITE|GENERIC_READ ,NULL,NULL,OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL,0); // 打开一个文件,获取文件句柄 设置属性为可读可写
if (NULL == hFile)
{
return NULL;
}
hMapping=::CreateFileMapping(hFile,NULL,PAGE_READWRITE ,0,dwSize,NULL); // 映射文件到内存 设置内存为可写
if (NULL == hMapping)
{
int i = GetLastError();
::CloseHandle(hFile);
return NULL;
}
ImageBase=::MapViewOfFile(hMapping,FILE_MAP_WRITE,0,0,0); // 获取映射的内存基址
CloseHandle(hFile);
CloseHandle(hMapping);
return ImageBase;
}