- 浏览: 17328 次
最新评论
内存映射对于大文件的使用
2011年04月28日
平时很少使用大文件的内存映射,碰巧遇到了这样的要求,所以把过程记录下来,当给各位一个引子吧,因为应用不算复杂,可能有考虑不到的地方,欢迎交流。
对于一些小文件,用普通的文件流就可以很好的解决,可是对于超大文件,比如2G或者更多,文件流就不行了,所以要使用API的内存映射的相关方法,即使是内存映射,也不能一次映射全部文件的大小,所以必须采取分块映射,每次处理一小部分。
先来看几个函数
CreateFile :打开文件
GetFileSize : 获取文件尺寸
CreateFileMapping :创建映射
MapViewOfFile :映射文件
看MapViewOfFile的帮助,他的最后两个参数都需要是页面粒度的整数倍,一般机器的页面粒度为64k(65536字节),而我们实际操作中,一般都不是这样规矩的,任意位置,任意长度都是可能的,所以就要做一些处理。
本例的任务是从一个长度列表中(FInfoList),依次读取长度值,然后到另外一个大文件(FSourceFileName)中去顺序读取指定长度的数据,如果是小文件,这个就好办了,一次读到文件流中,然后依次读取就是了,大数对于大文件,就需要不断改变映射的位置,来取得我们想要的数据。
本例中显示先通过GetSystemInfo来获取页面粒度,然后以10倍的页面粒度为一个映射数据块,在for循环中,会判断已经读取的长度(totallen)加上即将读取的长度,是否在本次映射范围之内(10倍的页面粒度),如果在就继续读取,如果超出了,就要记下剩下的数据,然后重新映射下一块内存,并将记录下的剩余数据合并到新读取的数据中,有点绕啊(可能是我的想法太绕了),下面列出代码。 procedure TGetDataThread.DoGetData; var FFile_Handle:THandle; FFile_Map:THandle; list:TStringList; p:PChar; i,interval:Integer; begin try totallen := 0; offset := 0; tstream := TMemoryStream.Create; stream := TMemoryStream.Create; list := TStringList.Create; //获取系统信息 GetSystemInfo(sysinfo); //页面分配粒度大小 blocksize := sysinfo.dwAllocationGranularity; //打开文件 FFile_Handle := CreateFile(PChar(FSourceFileName),GENERIC_READ,FIL E_SHARE_READ,nil,OPEN_EXISTING,FILE_ATTRIBUTE_NORMA L,0); if FFile_Handle = INVALID_HANDLE_VALUE then Exit; //获取文件尺寸 filesize := GetFileSize(FFile_Handle,nil); //创建映射 FFile_Map := CreateFileMapping(FFile_Handle,nil,PAGE_READONLY,0 ,0,nil); if FFile_Map = 0 then Exit; //此处我们已10倍blocksize为一个数据块来映射,如果文件尺寸小于10倍blocksize,则直接映射整个文件长度 if filesize div blocksize > 10 then readlen := 10*blocksize else readlen := filesize; for i := 0 to FInfoList.Count - 1 do begin list.Delimiter := ':'; list.DelimitedText := FInfoList.Strings[i]; //取得长度,我这里做了解析,因为我存储的信息为 a:b:c 这种类型,所以以:号分隔 len := StrToInt(list.Strings[1]); interval := StrToInt(list.Strings[2]); if (i = 0) or (totallen+len >=readlen) then begin //如果已读取的长度加上即将要读取的长度大于 10倍blocksize,那么我们要保留之前映射末尾的内容,以便和新映射的内容合并 if i > 0 then begin offset := offset + readlen; //写入临时流 tstream.Write(p^,readlen-totallen); tstream.Position := 0; end; //如果未读取的数据长度已经不够一个分配粒度,那么就直接映射剩下的长度 if filesize-offset 0 then begin //把临时流数据copy过来 stream.CopyFrom(tstream,tstream.Size); //然后在末尾写入新数据,合并完成 stream.Write(p^,len-tstream.Size); totallen := len-tstream.Size; //移动指针的位置,指向下一个数据的开始 Inc(p,len-tstream.Size); tstream.Clear; end else begin stream.Write(p^,len); totallen := totallen + len; Inc(p,len); end; stream.Position := 0; //将流保存成文件 stream.SaveToFile(IntToStr(i)+'.txt'); stream.Clear; end; finally stream.Free; tstream.Free; CloseHandle(FFile_Handle); CloseHandle(FFile_Map); end; end;
发表评论
-
MTD NAND Analysis 1
2012-01-20 08:14 706MTD NAND Analysis 1 2011年05月06 ... -
rtems 下linkcmd分析代码
2012-01-20 08:14 960rtems 下linkcmd分析代码 2010年11月09日 ... -
连傻瓜都能看懂的基于代码注入的线程守护技术
2012-01-20 08:14 1649连傻瓜都能看懂的基于 ... -
mmap内存映射操作之一
2012-01-20 08:14 1057mmap内存映射操作之一 2011年06月09日 本博客 ... -
S7-300 PLC的串口无线通讯在火电厂污水处理中的应用
2012-01-19 13:31 672S7-300 PLC的串口无线通讯 ... -
IIS32位和64位切换
2012-01-19 13:31 856IIS32位和64位切换 2011年12月22日 X64 ... -
两平台下的自动登录telnet设置
2012-01-19 13:30 630两平台下的自动登录telnet设置 2011年12月28日 ... -
延时批处理
2012-01-19 13:30 784延时批处理 2012年01月12日 举个例子,我们要延时 ... -
ActionScript垃圾回收
2012-01-17 03:20 944ActionScript垃圾回收 2011年10月26日 ... -
计算机故障大全(二)
2012-01-17 03:20 630计算机故障大全(二) 2010年06月02日 硬盘 ... -
琢石成器――windows环境下32位汇编语言程序设计(第三版)笔记
2012-01-17 03:20 2060琢石成器――windows环境下32位汇编语言程序设计(第三版 ... -
WinCE驱动开发问题精华集锦
2012-01-17 03:20 586WinCE驱动开发问题精华 ... -
钢蹦爸爸的自白
2012-01-16 01:54 658钢蹦爸爸的自白 2009年10月24日 怀着复杂的心情 ... -
爱韩庚的100个理由
2012-01-16 01:54 621爱韩庚的100个理由 2009 ... -
火车上的随想
2012-01-16 01:54 543火车上的随想 2011年02 ... -
jbpm3通过processDefinition.createProcessInstance()为什么能保存ProcessInstance之迷
2012-01-11 01:53 698jbpm3通过processDefinition.create ... -
Android自定义VIEW取得XML的自定义值
2012-01-11 01:53 665Android自定义VIEW取得XML的自定义值 2011年 ... -
常用的正则表达式--Java
2012-01-11 01:53 698常用的正则表达式--Java 2011年08月01日 是 ... -
图片传输问题,IO操作
2012-01-11 01:52 580图片传输问题,IO操作 2011年08月01日 原题: ... -
jsp编码过滤器的配置和使用-用心做程序-iteye技术网站
2012-01-11 01:52 677jsp编码过滤器的配置和使用-用心做程序-iteye技术网站 ...
相关推荐
实际工作中遇到超大文件读写时很多系统需要等待较长时间,给用户体验不佳。本文结合源码讲解了超大文件的内存映射读写方式。内存映射方式极大的提高了读写效率,提升用户体验感。
本文介绍利用内存映射文件修改大文件:在大文件内存前加入一段数据,若要使用内存映射文件,必须执行下列操作步骤: 1.创建或打开一个文件内核对象,该对象用于标识磁盘上你想用作内存映射文件的文件; 2.创建一个文件...
qt 内存 映射 大文件读写
文件操作是应用程序最为基本的功能之一,Win32 API和MFC均提供有支持文件处 理的函数和类...目前,对于上述这种大文件的操作一般是以内存映射文件的方式来加以处理的,本文下面将针对这种Windows核心编程技术展开讨论。
易语言内存映射大文件源码,内存映射大文件,创建映射,打开文件_,取颗粒数,映射内存,读基址,释放内存,关闭文件_,写入字节集,移动读写位置_,读位置指针,删除字节集,十六到十,映射_创建,API_取文件长度,API_打开文件,API...
关于内存映射文件读写文件的方法,大家学习了解一下
文件操作是应用程序最为基本的功能之一,Win32 API和MFC均提供有支持文件处理的函数和类...目前,对于上述这种大文件的操作一般是以内存映射文件的方式来加以处理的,本文下面将针对这种Windows核心编程技术展开讨论。
文件操作是应用程序最为基本的功能之一,Win32 API和MFC均提供有支持文件处理的函数和类...目前,对于上述这种大文件的操作一般是以内存映射文件的方式来加以处理的,本文下面将针对这种Windows核心编程技术展开讨论。
通过使用“内存映射文件”,实现内存共享 代码包含如何定义共享的内存结构、如何创建共享内存映射文件、如何多程序调用共享内存映射文件、如何由非创建方程序来释放共享内存映射文件
通过.net 4.0中的新类库使用内存映射文件
Visual C++ .NET环境下采用内存映射文件设计超大文件数据编辑器
用内存映射文件实现的共享内存封装类。 实现了数据读写互斥。
使用内存映射文件加快文件操作速度VB技术很实用的源码应网友要求,重新整理了此源码,没有的抓紧下载啊,
采用内存映射文件的方法处理大文件,快速有效的文件处理方式。
C++使用串口接收,内存映射文件处理大文件应用示例
VC++中使用内存映射编程方面的资料,希望对大家有用; 彻底共享,决不要分!
主要介绍了Delphi 中内存映射对于大文件的使用的相关资料,希望通过本文能帮助到大家,需要的朋友可以参考下
8.4.2 使用内存映射文件读BMP文件的例子
利用内存映射文件技术实现进程间通信,自pudn程序员联合开发网下载