用内存映射文件读取大型文件

来源:互联网 发布:查看交换机端口ip地址 编辑:程序博客网 时间:2024/04/28 21:36

引言

通常情况下,我们使用文件读写函数对文件进行处理,比如Win32 API 的CreateFile()、WriteFile()、ReadFile()等。

但是对于某些特殊应用领域,需要几十GB、几百GB的海量存储,常规处理方法显然行不通了,目前对于这种大文件的操作一般是以内存映射的方式来加以处理的。

CreateFile():用来创建一个读文件的句柄;

CreateFileMapping():创建一个文件映射对象;

MapViewOfFile(): 获得文件第一个字节的指针,通过该指针可以得到文件中的全部内容

最后,CloseHandle()关闭文件对象和文件映射对象;

UnmapViewOfFile():用来释放文件数据映射。

实践

在书上看了几个例子,虽然对小型文件访问成功,但是对于大型文件就不行了——出错,可见作者也没有真正将“访问大型文件”的优势,在代码中体现出来——如果仅仅是读取小文件、几个字节,我何必使用文件映射这么麻烦的手段呢?

不过好在天无绝人之路,一边自己尝试、一边google相关的资料,终于解决了大型文件访问的问题;我映射了一个2GB的ghost文件,成功......

在此感谢:http://tech.ccidnet.com/art/1081/20060410/501669_1.html (搜索:MapViewOfFile、大型文件映射、映射文件、代码,找到这篇文章,其中部分文字描述与书上雷同)

SYSTEM_INFO sinf;GetSystemInfo(&sinf);DWORD dwAllocationGranularity = sinf.dwAllocationGranularity;// 创建文件内核对象,其句柄保存于hFileHANDLE hFile = CreateFile("d://sys.GHO",GENERIC_WRITE | GENERIC_READ,FILE_SHARE_READ, NULL,CREATE_ALWAYS, FILE_FLAG_SEQUENTIAL_SCAN, NULL);// 创建文件映射内核对象,句柄保存于hFileMappingHANDLE hFileMapping = CreateFileMapping(hFile,NULL,PAGE_READWRITE, 0, 0x4000000, NULL);// 释放文件内核对象CloseHandle(hFile);// 设定大小、偏移量等参数__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);

应用举例

这里有一个简单例子:http://www.cnblogs.com/stuarts/archive/2010/07/08/1773844.html 

说它简单,因为:1. 数据样本简单(整个文件中全部是int数);2. 排序算法简单(冒泡)。

程序功能:将外部文件映射为一块内存,使用指针排序。

该例子说明:1 使用内存映射文件,可以避免“外排序”算法复杂度较高的尴尬;2 实现代码简单、结构清晰。

替代方案

C#里面使用Read、ReadLine方法、Stream类库,可以很方便地读取、写入大于4G的文件(未编程验证)。

 

 

原创粉丝点击