关于内存映射来修改文件,并改变文件的大小

 内存映射是为了方便多个进程间的共同开发从而共享一段内存,但是,它还有一个其他功能,那就是修改文件

在内存映射之前,首先我们需要用 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;

}


你可能感兴趣的:(系统API)