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

引言

通常情况下,我们使用文件读写函数对文件进行处理,比如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;
// 创建文件内核对象,其句柄保存于hFile
HANDLE hFile = CreateFile("d://sys.GHO",
GENERIC_WRITE | GENERIC_READ,
FILE_SHARE_READ, 
NULL,
CREATE_ALWAYS, 
FILE_FLAG_SEQUENTIAL_SCAN, 
NULL);
// 创建文件映射内核对象,句柄保存于hFileMapping
HANDLE 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的文件(未编程验证)。

 

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值