文件管理 · 2024年9月7日

内存映射文件实例|怎样用C++内存映射磁盘文件的方式映射一个几百M的文件还有几十M还有几十K的文件

『壹』 鍐呭瓨鏄犲皠鏂囦欢鐨勫簲鐢ㄧず渚

涓嬮潰缁撳悎涓涓鍏蜂綋鐨勫疄渚嬫潵杩涗竴姝ヨ茶堪鍐呭瓨鏄犲皠鏂囦欢鐨勪娇鐢ㄦ柟娉曘傝ュ疄渚嬩粠绔鍙f帴鏀舵暟鎹锛屽苟瀹炴椂灏嗗叾瀛樻斁浜庣佺洏锛岀敱浜庢暟鎹閲忓ぇ锛堝嚑鍗丟B锛夛紝鍦ㄦら夌敤鍐呭瓨鏄犲皠鏂囦欢杩涜屽勭悊銆備笅闈㈢粰鍑虹殑鏄浣嶄簬宸ヤ綔绾跨▼MainProc涓鐨勯儴鍒嗕富瑕佷唬鐮侊紝璇ョ嚎绋嬭嚜绋嬪簭杩愯屾椂鍚鍔锛屽綋绔鍙f湁鏁版嵁鍒拌揪鏃跺皢浼氬彂鍑轰簨浠秇Event[0]锛學aitForMultipleObjects锛堬級鍑芥暟绛夊緟鍒拌ヤ簨浠跺彂鐢熷悗灏嗘帴鏀跺埌鐨勬暟鎹淇濆瓨鍒扮佺洏锛屽傛灉缁堟㈡帴鏀跺皢鍙戝嚭浜嬩欢hEvent[1]锛屼簨浠跺勭悊杩囩▼灏嗚礋璐e畬鎴愯祫婧愮殑閲婃斁鍜屾枃浠剁殑鍏抽棴绛夊伐浣溿備笅闈㈢粰鍑烘ょ嚎绋嬪勭悊鍑芥暟鐨勫叿浣撳疄鐜拌繃绋嬶細// 鍒涘缓鏂囦欢鍐呮牳瀵硅薄锛屽叾鍙ユ焺淇濆瓨浜巋FileHANDLE hFile = CreateFile(Recv1.zip,GENERIC_WRITE | GENERIC_READ,FILE_SHARE_READ,NULL,CREATE_ALWAYS,FILE_FLAG_SEQUENTIAL_SCAN,NULL);// 鍒涘缓鏂囦欢鏄犲皠鍐呮牳瀵硅薄锛屽彞鏌勪繚瀛樹簬hFileMappingHANDLE hFileMapping = CreateFileMapping(hFile,NULL,PAGE_READWRITE,0,0×4000000,NULL);// 閲婃斁鏂囦欢鍐呮牳瀵硅薄CloseHandle(hFile);// 璁惧畾澶у皬銆佸亸绉婚噺绛夊弬鏁 // 灏介噺鎶婃枃浠惰剧疆澶т竴浜涳紝 濡傛灉鍐欑殑鏁版嵁瓒呰繃锛岃惧畾鐨勫硷紝鍐嶆℃槧灏勬枃浠朵細鎶ラ敊 getlasterror = 183;__int64 qwFileSize = 0x4000000;__int64 qwFileOffset = 0;__int64 T = 600 * sinf.dwAllocationGranularity;DWORD dwBytesInBlock = 1000 * sinf.dwAllocationGranularity;// 灏嗘枃浠舵暟鎹鏄犲皠鍒拌繘绋嬬殑鍦板潃绌洪棿PBYTE pbFile = (PBYTE)MapViewOfFile(hFileMapping,FILE_MAP_ALL_ACCESS,(DWORD)(qwFileOffset>>32),(DWORD)(qwFileOffset&0xFFFFFFFF),dwBytesInBlock);while(bLoop){// 鎹曡幏浜嬩欢hEvent[0]鍜屼簨浠秇Event[1]DWORD ret = WaitForMultipleObjects(2,hEvent,FALSE,INFINITE);ret -= WAIT_OBJECT_0;switch (ret){// 鎺ユ敹鏁版嵁浜嬩欢瑙﹀彂case 0:// 浠庣鍙f帴鏀舵暟鎹骞朵繚瀛樺埌鍐呭瓨鏄犲皠鏂囦欢nReadLen=syio_Read(port[1],pbFile + qwFileOffset,QueueLen);qwFileOffset += nReadLen;// 褰撴暟鎹鍐欐弧60%鏃讹紝涓洪槻鏁版嵁婧㈠嚭锛岄渶瑕佸湪鍏跺悗寮杈熶竴鏂扮殑鏄犲皠瑙嗗浘if (qwFileOffset > T){T = qwFileOffset + 600 * sinf.dwAllocationGranularity;UnmapViewOfFile(pbFile);pbFile = (PBYTE)MapViewOfFile(hFileMapping,FILE_MAP_ALL_ACCESS,(DWORD)(qwFileOffset>>32),(DWORD)(qwFileOffset&0xFFFFFFFF),dwBytesInBlock);}break;// 缁堟浜嬩欢瑙﹀彂case 1:bLoop = FALSE;// 浠庤繘绋嬬殑鍦板潃绌洪棿鎾ゆ秷鏂囦欢鏁版嵁鏄犲儚UnmapViewOfFile(pbFile);// 鍏抽棴鏂囦欢鏄犲皠瀵硅薄CloseHandle(hFileMapping);break;}}鈥鍦ㄧ粓姝浜嬩欢瑙﹀彂澶勭悊杩囩▼涓濡傛灉鍙绠鍗曠殑鎵ц孶nmapViewOfFile锛堬級鍜孋loseHandle锛堬級鍑芥暟灏嗘棤娉曟g‘鏍囪瘑鏂囦欢鐨勫疄闄呭ぇ灏忥紝鍗冲傛灉寮杈熺殑鍐呭瓨鏄犲皠鏂囦欢涓30GB锛岃屾帴鏀剁殑鏁版嵁鍙鏈14GB锛岄偅涔堜笂杩扮▼搴忔墽琛屽畬鍚庯紝淇濆瓨鐨勬枃浠堕暱搴︿粛鏄30GB銆備篃灏辨槸璇达紝鍦ㄥ勭悊瀹屾垚鍚庤繕瑕佸啀娆¢氳繃鍐呭瓨鏄犲皠鏂囦欢鐨勫舰寮忓皢鏂囦欢鎭㈠嶅埌瀹為檯澶у皬锛屼笅闈㈡槸瀹炵幇姝よ佹眰鐨勪富瑕佷唬鐮侊細// 鍒涘缓鍙﹀栦竴涓鏂囦欢鍐呮牳瀵硅薄hFile2 = CreateFile(Recv.zip,GENERIC_WRITE | GENERIC_READ,FILE_SHARE_READ,NULL,CREATE_ALWAYS,FILE_FLAG_SEQUENTIAL_SCAN,NULL);// 浠ュ疄闄呮暟鎹闀垮害鍒涘缓鍙﹀栦竴涓鏂囦欢鏄犲皠鍐呮牳瀵硅薄hFileMapping2 = CreateFileMapping(hFile2,NULL,PAGE_READWRITE,0,(DWORD)(qwFileOffset&0xFFFFFFFF),NULL);// 鍏抽棴鏂囦欢鍐呮牳瀵硅薄CloseHandle(hFile2);// 灏嗘枃浠舵暟鎹鏄犲皠鍒拌繘绋嬬殑鍦板潃绌洪棿pbFile2 = (PBYTE)MapViewOfFile(hFileMapping2,FILE_MAP_ALL_ACCESS,0,0,qwFileOffset);// 灏嗘暟鎹浠庡師鏉ョ殑鍐呭瓨鏄犲皠鏂囦欢澶嶅埗鍒版ゅ唴瀛樻槧灏勬枃浠memcpy(pbFile2,pbFile,qwFileOffset);file://浠庤繘绋嬬殑鍦板潃绌洪棿鎾ゆ秷鏂囦欢鏁版嵁鏄犲儚UnmapViewOfFile(pbFile);UnmapViewOfFile(pbFile2);// 鍏抽棴鏂囦欢鏄犲皠瀵硅薄CloseHandle(hFileMapping);CloseHandle(hFileMapping2);// 鍒犻櫎涓存椂鏂囦欢DeleteFile(Recv1.zip);

『贰』 内存映射文件 存储空间不够、

设一个偏移量,不要映射那么多。下面是别人的处理方法,抄来给你:使用内存映射文件处理大文件的代码示例:1 SYSTEM_INFO sinf;2 GetSystemInfo(&sinf);3 4 // Open the file for reading and writing.5 HANDLE hFile = CreateFile(pszPathname, GENERIC_WRITE | GENERIC_READ, 0,6 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);7 if (hFile == INVALID_HANDLE_VALUE) {8 chMB("File could not be opened.");9 return(FALSE);10 }11 12 // Get the size of the file (I assume the whole file can be mapped) in bytes.13 DWORD dwFileSize = GetFileSize(hFile, NULL);14 15 // Create the file-mapping object.16 HANDLE hFileMap = CreateFileMapping(hFile, NULL, PAGE_READWRITE,17 0, dwFileSize, NULL);18 if (hFileMap == NULL) {19 chMB("File map could not be opened.");20 CloseHandle(hFile);21 return(FALSE);22 }23 24 DWORD map_data_offset = 0;25 DWORD bytes_mapped = sinf.dwAllocationGranularity;26 PVOID pvFile = NULL;27 PSTR ps_ptr = NULL;28 29 while(dwFileSize > 0)30 {31 if(dwFileSize < bytes_mapped)32 {33 pvFile = MapViewOfFile(hFileMap, FILE_MAP_WRITE, 0, map_data_offset, dwFileSize);34 //对字符数组pvFile的处理35 map_data_offset += dwFileSize;36 dwFileSize = 0;37 }38 else39 {40 pvFile = MapViewOfFile(hFileMap,FILE_MAP_WRITE,0,map_data_offset,bytes_mapped);41 //对字符数组pvFile的处理42 map_data_offset += bytes_mapped;43 dwFileSize -= bytes_mapped;44 }45 }46 // Clean up everything before exiting.47 UnmapViewOfFile(pvFile);48 CloseHandle(hFileMap);49 // Remove trailing zero character added earlier.50 SetFilePointer(hFile, dwFileSize, NULL, FILE_BEGIN);51 CloseHandle(hFile);文件映射对象存储于内核地址范围是所有操作系统的进程共享的,而MapViewOfFile文件映射地址空间是存在于进程的私有地址空间中,要想指定地址空间首地址可用MapViewOfFileEx函数,但只是建议首地址。

『叁』 怎样用C++内存映射磁盘文件的方式映射一个几百M的文件,还有几十M,还有几十K的文件

#include <windows.h>#include <tchar.h>#include <stdio.h>int main(){HANDLE hFile = CreateFile(_T(“1.txt”), GENERIC_READ | GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0);if (hFile == INVALID_HANDLE_VALUE) {puts(“fail to create file”);goto fail_open;}SetFileValidData(hFile, 1024);HANDLE hMap = CreateFileMapping(hFile, 0, PAGE_READWRITE, 0, 1024, 0);if (hMap == NULL) {puts(“fail to create mapping”);goto fail_map;}LPVOID pContent = MapViewOfFile(hMap, FILE_MAP_WRITE, 0, 0, 1024);if (pContent == 0) {puts(“fail to open mapping”);goto fail_view;}//好了,此时这个文件就相当于你用malloc申请的一个1024字节的内存空间。char* pStr = (char*) pContent;strcpy(pStr, “hahaha”);UnmapViewOfFile(pContent);fail_view:CloseHandle(hMap);fail_map:CloseHandle(hFile);fail_open:return 0;}

『肆』 我c++要处理大量数据,一个都是几百m,如何存入内存.

用内存映射应该行的。内存映射就是把一个文件当作一块内存区域用。 类别: 内存映射文件 题目:对一个文件使用内存映射文件 Demo: 1:创建或打开一个文件内核对象: // Open the file for reading and writing. HANDLE hFile = CreateFile(pszPathname, GENERIC_WRITE | GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); // 由于hFile即使为INVALID_HANDLE_VALUE,下面的CreateFileMapping仍然可以正常运行, // 所以这里一定要对hFile进行检查! if (hFile == INVALID_HANDLE_VALUE) { chMB("File could not be opened."); return(FALSE); } 2:创建一个文件映射内核对象: // Get the size of the file (I assume the whole file can be mapped). DWORD dwFileSize = GetFileSize(hFile, NULL); // 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. HANDLE hFileMap = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, dwFileSize + sizeof(WCHAR), // 如果该文件小于设定的大小,本函数将扩展该文件的大小, // 使磁盘上的文件变大。这样当以后将该文件作为内存映射 // 文件使用时,物理存储器就已经存在了。 NULL f// 这个文件映射对象的名字用于与其他进程共享该对象,这里我们还用不到。 ); if (hFileMap == NULL) { chMB("File map could not be opened."); CloseHandle(hFile); return(FALSE); } 3:将文件数据映射到进程的地址空间: 当创建了一个文件映射对象之后,仍然必须让系统为文件的数据保留一个地址空间区域, 并将文件的数据作为映射到该区域的物理存储器进行提交。 // Get the address where the first byte of the file is mapped into memory. // the return value is the starting address of the mapped view: PVOID pvFile = MapViewOfFile(hFileMap, FILE_MAP_WRITE, 0, 0, 0); if (pvFile == NULL) { chMB("Could not map view of file."); CloseHandle(hFileMap); CloseHandle(hFile); return(FALSE); } 4:既然我们通过pvFile得到了映象视图的起始地址,那么可以对视图做一些操作了: ANSI版本: PSTR pchANSI = (PSTR) pvFile; UNICODE版本: PWSTR pchUnicode = (PWSTR) pvFile; 5:从进程的地址空间中撤销文件数据的映象: // Clean up everything before exiting. UnmapViewOfFile(pvFile); 6:关闭文件映射对象和文件对象: CloseHandle(hFileMap); CloseHandle(hFile); Definition: HANDLE CreateFileMapping( HANDLE hFile, // handle to file LPSECURITY_ATTRIBUTES lpAttributes, // security DWORD flProtect, // protection DWORD dwMaximumSizeHigh, // high-order DWORD of size DWORD dwMaximumSizeLow, // low-order DWORD of size LPCTSTR lpName // object name ); LPVOID MapViewOfFile( HANDLE hFileMappingObject, // handle to file-mapping object DWORD dwDesiredAccess, // access mode DWORD dwFileOffsetHigh, // high-order DWORD of offset DWORD dwFileOffsetLow, // low-order DWORD of offset SIZE_T dwNumberOfBytesToMap // number of bytes to map ); BOOL UnmapViewOfFile( LPCVOID lpBaseAddress // starting address ); Tips: 也可以尽量早地把对象关闭,以消除资源泄漏的可能性,如: HANDLE hFile = CreateFile(…); HANDLE hFileMapping = CreateFileMapping(hFile,…); CloseHandle(hFile); PVOID pvFile = MapViewOfFile(hFileMapping,…); CloseHandle(hFileMapping); // use the memory-mapped file. UnmapViewOfFile(pvFile);