woaidongmao

文章均收录自他人博客,但不喜标题前加-[转贴],因其丑陋,见谅!~
随笔 - 1469, 文章 - 0, 评论 - 661, 引用 - 0
数据加载中……

用MapViewOfFile处理大文件-内存不足

MapViewOfFile处理大文件时,如果文件过大,如400M,则无法一次性映射入内存,否则会出现1132错误,即内存不足。原因可能为操作系统无法找到连续的内存。因此需要通过分页的方式,逐页将文件内容映射到内存。
相关资料:
LPVOID MapViewOfFile(HANDLE hFileMappingObject,

  DWORD dwDesiredAccess,

  DWORD dwFileOffsetHigh,

  DWORD dwFileOffsetLow,

  DWORD dwNumberOfBytesToMap);

  MapViewOfFile()函数负责把文件数据映射到进程的地址空间,参数hFileMappingObject CreateFileMapping()返回的文件映像对象句柄。参数dwDesiredAccess则再次指定了对文件数据的访问方式,而且同样要与 CreateFileMapping()函数所设置的保护属性相匹配。虽然这里一再对保护属性进行重复设置看似多余,但却可以使应用程序能更多的对数据的保护属性实行有效控制。MapViewOfFile()函数允许全部或部分映射文件,在映射时,需要指定数据文件的偏移地址以及待映射的长度。其中,文件的偏移地址由DWORD型的参数dwFileOffsetHighdwFileOffsetLow组成的64位值来指定,而且必须是操作系统的分配粒度的整数倍,对于Windows操作系统,分配粒度固定为64KB。当然,也可以通过如下代码来动态获取当前操作系统的分配粒度:

  SYSTEM_INFO sinf;

  GetSystemInfo(&sinf);

  DWORD dwAllocationGranularity = sinf.dwAllocationGranularity;

  参数dwNumberOfBytesToMap指定了数据文件的映射长度,这里需要特别指出的是,对于Windows 9x操作系统,如果MapViewOfFile()无法找到足够大的区域来存放整个文件映射对象,将返回空值(NULL);但是在Windows 2000下,MapViewOfFile()只需要为必要的视图找到足够大的一个区域即可,而无须考虑整个文件映射对象的大小。

由此看出,分页映射文件时,每页的起始位置startpos,必须为64K的整数倍。

HANDLE hFile=::CreateFile("c:\\111.dwf",GENERIC_READ,FILE_SHARE_READ | FILE_SHARE_WRITE,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_READONLY,NULL);

////////////////////////////////////////////////////////////////////
// CreateFileMapping
dwMaximumsize必须设置为0,否则MapViewOfFileoffset>0时,映射失败
HANDLE m_hCurFileMap = CreateFileMapping
    (    hFile,    NULL,    PAGE_READONLY,    0,     0,    NULL    );
DWORD offset=64*1024;
LPVOID m_pReadBuffer=MapViewOfFile(m_hCurFileMap,FILE_MAP_READ,
   (DWORD)0,
   (DWORD)(offset & 0xFFFFFFFF),
   offset
   );

 

就个人使用情况而言,使用内存映射并不见得比使用流处理要快,前提是流操作的当的话

 

如果文件没有碎片,流是不慢的,但是如果磁盘碎片很多,你用流处理100M的文件要1分钟,可能你处理200M的文件就要3分钟。

 

采用分页机制吧。
例如设定每次映射大小为50M,首先映射第一个50M,处理完后,映射第二个50M
FileMapping
本身支持offset的。

 

 

posted on 2011-02-16 17:52 肥仔 阅读(7201) 评论(0)  编辑 收藏 引用 所属分类: Windows开发


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理