首先介绍内存映射文件操作------函数的用法以及先后执行顺序 // 第一步:创建文件 HANDLE hFile = CreateFileForMapping(_T("MyMemFile.dat"), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); ASSERT(hFile != 0); // 第二步:创建内存映射文件对象 HANDLE hMapFile = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 1024, _T("MyMapppingFile")); ASSERT(hMapFile != 0); // 第三步:获取内存映射文件对象视图 BYTE* pData = (BYTE*)MapViewOfFile(hMapFile, FILE_MAP_WRITE, 0, 0, 1024); ASSERT(pData != NULL); // 对 pData 指针进行读写操作 // ...... // 第四步:取消内存视图映射 UnmapViewOfFile(pData); // 第五步:关闭内存映射对象句柄 CloseHandle(hMapFile); // 第六步:关闭文件句柄 CloseHandle(hFile); =================================header file========================================= // MapFile.h : header file #if !defined(AFX_MAPFILE_H__D067E5C8_C4D7_4569_A6BB_9D651FB3F396__INCLUDED_) #define AFX_MAPFILE_H__D067E5C8_C4D7_4569_A6BB_9D651FB3F396__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 / // CMapFile class 使用说明: // 1 一个对象,打开文件映射之后,立即处理,处理完之后才能再用它打开另一个文件映射 class CMapFile { public: CMapFile(); // protected constructor used by dynamic creation virtual ~CMapFile(); // Attributes public: PVOID m_pvFile; BOOL m_bSmooth; // 为TRUE表示不阻塞,即不弹出任何对话框 private: HANDLE hFileMap; // Operations public: BOOL OpenMapFile(CString sFile); // Implementation public: BOOL CloseMapFile(); }; //{{AFX_INSERT_LOCATION}} // Microsoft Visual C++ will insert additional declarations immediately before the previous line. #endif // !defined(AFX_MAPFILE_H__D067E5C8_C4D7_4569_A6BB_9D651FB3F396__INCLUDED_) =========================================implementation file=========================== // MapFile.cpp : implementation file #include "stdafx.h" #include "MapFile.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif / // CMapFile CMapFile::CMapFile() { m_pvFile=NULL; m_bSmooth=FALSE; } CMapFile::~CMapFile() { if(NULL!=m_pvFile) { UnmapViewOfFile(m_pvFile); m_pvFile=NULL; } } / // CMapFile operation handlers // 空文件会弹出 map could not be opened,在里面敲一个回车,就好了 BOOL CMapFile::OpenMapFile(CString sFile) { if(NULL!=m_pvFile) { UnmapViewOfFile(m_pvFile);//在当前应用程序的内存地址空间解除对一个文件映射对象的映射 m_pvFile=NULL; } // 1:创建或打开一个文件内核对象: Open the file for reading and writing. // 这里CreateFile函数的参数,路径无论是否有空格都不能有引号,有引号的时候会出错。 HANDLE hFile = CreateFile(sFile,GENERIC_READ|GENERIC_WRITE, 0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL); // 由于hFile即使为INVALID_HANDLE_VALUE,下面的CreateFileMapping仍然可以正常运行, // 所以这里一定要对hFile进行检查! if (hFile == INVALID_HANDLE_VALUE) { if(!m_bSmooth) // 为TRUE表示不阻塞,即不弹出任何对话框 { AfxMessageBox(_T("File[")+sFile+_T("]could not be opened. Maybe it's not exist.")); } return FALSE; } // 2:创建一个文件映射内核对象 DWORD dwFileSize = GetFileSize(hFile, NULL); //获取文件大小=文件长度+(WCHAR)'/0'(ssume the whole file can be mapped) // Create the file-mapping object. The file-mapping object is 1 character // bigger than the file size so that a zero character can be placed at the // end of the file to terminate the string (file). Because I don't yet know // if the file contains ANSI or Unicode characters, I assume worst case // and add the size of a WCHAR instead of CHAR. hFileMap = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, dwFileSize+1, /*sizeof(WCHAR)==2,sizeof(char)==1*/ //因为我们要在文件的末尾加上一个字符串的结束符'/0', 当我们将这个文件映射到内存中时, //我们就可以像操作字符串一样地来操作文件了。 //如果该文件小于设定的大小,本函数将扩展该文件的大小,使磁盘上的文件变大。这样当以后将该文件作为内存映射 文件使用时,物理存储器就已经存在了。 NULL // 这个文件映射对象的名字用于与其他进程共享该对象,这里我们还用不到。 ); if (hFileMap == NULL) { if(!m_bSmooth) { AfxMessageBox(_T("File[")+sFile+_T("] map could not be opened. May be it's empty.")); } return FALSE; } // 3:将文件数据映射到进程的地址空间: // 当创建了一个文件映射对象之后,仍然必须让系统为文件的数据保留一个地址空间区域, // 并将文件的数据作为映射到该区域的物理存储器进行提交。 m_pvFile = MapViewOfFile(hFileMap,/*FILE_MAP_WRITE*/FILE_MAP_READ,0,0,0);//获取映射文件在内存中的首地址 //CloseHandle(hFileMap);// 关闭内存映射对象句柄 if (m_pvFile == NULL) { if(!m_bSmooth) { AfxMessageBox(_T("Could not map view of file[")+sFile+_T("].")); } return FALSE; } // 4:既然我们通过pvFile得到了映象视图的起始地址,那么可以对视图做一些操作了: // ANSI版本: // PSTR pchANSI = (PSTR) m_pvFile; // UNICODE版本: // PWSTR pchUnicode = (PWSTR) pvFile;如char* sz=(char*)m_pvFile;sz[dwFileSize/sizeof(char)]='/0'; // 5:从进程的地址空间中撤销文件数据的映象: // UnmapViewOfFile(m_pvFile); // 封装为类,映象要在其他地方使用所以这句话要去掉 // 6:关闭文件映射对象和文件对象: // CloseHandle(hFileMap); //我们改变了文件的长度,因此要重新设置文件的结束符以删除留在文件尾部的多余内容(比如删除我们先前加到文件末尾的'/0'字符) SetFilePointer(hFile,dwFileSize, NULL, FILE_BEGIN); SetEndOfFile(hFile); //设定当前文件指针所在处为文件结束处.该处后面的内容将被删除 CloseHandle(hFile); return TRUE; } BOOL CMapFile::CloseMapFile() { if(NULL!=m_pvFile) { //取消内存视图映射 if(UnmapViewOfFile(m_pvFile)) { m_pvFile=NULL; CloseHandle(hFileMap);// 关闭内存映射对象句柄 return TRUE; } return FALSE; } return TRUE; }
c++/MFC 封装好的文件内存映射类
最新推荐文章于 2021-12-12 07:13:54 发布