通过内存映射文件操作大型文件

Posted on 2014-10-16 00:20  XCPP  阅读(355)  评论(0编辑  收藏  举报

参考来源:http://www.cnblogs.com/stuarts/archive/2010/07/08/1773844.htm

内存映射,说简单点就像符号链接(类似比喻,大家匆喷。。。)一样。它可以在不增大过多内存开销的同时,又能快速(来自网上:比I/O读写要快20倍)处理GB级别以上的大型文件。

实现步骤:

1.CreateFile

2.CreateFileMapping

3.MapViewOfFile

通过MapViewOfiFile便可得到一个可以直接操作文件的内存地址。

注意:

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
);
第五个参数,dwNumberOfBytesToMap指定要映射的字节大小,需由内存分配粒度的值乘以1000得到(如果文件大小小于乘积,则使用实际文件大小)。
详细原理自行谷歌。
由此可知,当对文件的操作达到或接近文件末端时,须以下一块文件的偏移值或当前指针位置加一的值重新映射。

关键代码:
提取于文章开头来源网址的博文中(在此表示感谢原博主!)
 1 // 得到hFileMap之后,hFileMap = CreateFileMapping()
 2 if (hFileMap == NULL)
 3     {
 4         printf("创建文件映射对象失败,错误代码:%drn", GetLastError());
 5         return -1;
 6     }
 7     // 得到内存分配粒度
 8     SYSTEM_INFO SysInfo;
 9     GetSystemInfo(&SysInfo);
10     DWORD dwGran = SysInfo.dwAllocationGranularity;
11     // 得到文件尺寸
12     DWORD dwFileSizeHigh;
13     __int64 qwFileSize = GetFileSize(hFile, &dwFileSizeHigh);
14     qwFileSize |= (((__int64)dwFileSizeHigh) << 32);
15     // 关闭文件对象
16     CloseHandle(hFile);
17     // 偏移地址
18     __int64 qwFileOffset = 0;
19     // 块大小:在映射过程中设定每次映射的块大小为1000倍的分配粒度
20     DWORD dwBlockBytes = 1000 * dwGran;
21     if (qwFileSize < 1000 * dwGran)
22         dwBlockBytes = (DWORD)qwFileSize;
23     while (qwFileSize > 0)
24     {
25         // 映射视图,LPVOID可根据需要转换成实际类型
26         LPVOID lpbMapAddress = (LPVOID)MapViewOfFile(hFileMap,FILE_MAP_ALL_ACCESS,
27             (DWORD)(qwFileOffset >> 32) , (DWORD)(qwFileOffset & 0xFFFFFFFF), /*不同长度的位运算右端对齐*/
28             dwBlockBytes);
29         if (lpbMapAddress == NULL)
30         {
31             printf("映射文件映射失败,错误代码:%drn", GetLastError());
32             return -1;
33         }
34         const int NUMBER_MAX_LENGTH = 6;
35         // 对映射的视图进行访问
36         char temp[NUMBER_MAX_LENGTH + 1] = {0};
37         int number = 0;
38         //直接操作内存lpbMapAddress,此时lpbMapAddress即为一个内存地址,但为磁盘文件的分块映射
39         
40         // 对文件的详细操作。。。
41         
42         // 撤消文件映像
43         UnmapViewOfFile(lpbMapAddress);
44         // 修正参数,为映射下一块文件作准备
45         qwFileOffset += dwBlockBytes;
46         qwFileSize -= dwBlockBytes;
47     }
48     // 关闭文件映射对象句柄
49     CloseHandle(hFileMap);
50     return 0;
51 }

现学,只得其皮毛。