VC利用内存映射文件处理大文件
内存映射原理

内存映射原理
内存映射是一种将磁盘文件映射到内存的操作。
在内存中建立一个虚拟地址空间,该空间与磁盘文件相对应,使得我们可以像访问内存一样访问磁盘文件的内容。
内存映射的原理是通过将磁盘文件的内容映射到内存的一段连续地址空间中。
在内存中指定一个缓冲区,当对这个缓冲区进行读写操作时,实际上是在对磁盘文件进行读写操作。
读取该内存区域的数据时,由于数据已经在内存中,所以读取速度非常快。
内存映射的过程主要包括以下几个步骤:
1. 打开文件:使用文件操作相关的API函数打开需要映射到内存的文件。
2. 创建映射区域:使用内存映射相关的API函数,创建一个映射区域。
将文件的某个区域映射到内存。
3. 访问映射区域:获得映射到内存中的虚拟地址,可以直接对其进行读写操作,就像操作内存一样。
4. 保存修改:如果对映射区域进行了修改,需要使用相关的API函数将修改的内容保存回磁盘文件。
通过内存映射,可以实现大文件的快速读写,提高文件的访问速度。
此外,多个进程可以通过映射同一个文件,实现共享内
存的功能,简化进程间通信的实现。
但需要注意的是,对于大文件的内存映射可能会消耗大量的系统内存,需要进行适当的调优和管理。
内存映射文件的作用功能介绍

内存映射文件的作用功能介绍内存映射文件的主要用途:1.操作大文件 2.进程间大量数据共享,下面分别介绍如下:VC++中使用内存映射文件处理大文件引言文件操作是应用程序最为基本的功能之一,Win32 API和MFC均提供有支持文件处理的函数和类,常用的有Win32 API的CreateFile()、WriteFile()、ReadFile()和MFC提供的CFile类等。
一般来说,以上这些函数可以满足大多数场合的要求,但是对于某些特殊应用领域所需要的动辄几十GB、几百GB、乃至几TB的海量存储,再以通常的文件处理方法进行处理显然是行不通的。
目前,对于上述这种大文件的操作一般是以内存映射文件的方式来加以处理的,本文下面将针对这种Windows核心编程技术展开讨论。
内存映射文件内存映射文件与虚拟内存有些类似,通过内存映射文件可以保留一个地址空间的区域,同时将物理存储器提交给此区域,只是内存文件映射的物理存储器来自一个已经存在于磁盘上的文件,而非系统的页文件,而且在对该文件进行操作之前必须首先对文件进行映射,就如同将整个文件从磁盘加载到内存。
由此可以看出,使用内存映射文件处理存储于磁盘上的文件时,将不必再对文件执行I/O操作,这意味着在对文件进行处理时将不必再为文件申请并分配缓存,所有的文件缓存操作均由系统直接管理,由于取消了将文件数据加载到内存、数据从内存到文件的回写以及释放内存块等步骤,使得内存映射文件在处理大数据量的文件时能起到相当重要的作用。
另外,实际工程中的系统往往需要在多个进程之间共享数据,如果数据量小,处理方法是灵活多变的,如果共享数据容量巨大,那么就需要借助于内存映射文件来进行。
实际上,内存映射文件正是解决本地多个进程间数据共享的最有效方法。
内存映射文件并不是简单的文件I/O操作,实际用到了Windows的核心编程技术--内存管理。
所以,如果想对内存映射文件有更深刻的认识,必须对Windows操作系统的内存管理机制有清楚的认识,内存管理的相关知识非常复杂,超出了本文的讨论范畴,在此就不再赘述,感兴趣的读者可以参阅其他相关书籍。
VC++ 中WM_COPYDATA 怎么样应用来实现两个进程间的数据传输

HWND hWnd = FindWindow(NULL,"MyApp");
if(hWnd!=NULL)
{
COPYDATASTRUCT cpd; /*给COPYDATASTRUCT结构赋值*/
cpd.dwData = 0;
cpd.cbData = strlen("字符串");
{
AfxMessageBox((LPCSTR)(pCopyDataStruct->lpData));/*利用对话框表示收到消息*/
return CWnd::OnCopyData(pWnd, pCopyDataStruct);
}
进程通信还有其他一些手段,相对来说比较麻烦,但局限性要比WM_COPYDATA小。当然你也可以两端都注册一个消息来通信。
afx_msg BOOL OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct);
ON_WM_COPYDATA()/*消息映射*/
BOOL CMainFrame::OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct)
进程间通信的方法有多种,其中,对于少量数据可以用WM_COPYDATA方便的实现通信(如果对于大量数据的话,由于SendMessage是阻塞的,只有接收方响应了消息,SendMessage才能返回,否则则一直阻塞,所以,对于大量数据来说,用SendMessage就容易造成窗口假死) 。
ห้องสมุดไป่ตู้
本例子分别用WM_COPYDATA 实现了两种数据类型的发送,一种为Cstring,另外一种为自定义的结构体Student:
VC6.0在32位机中对大数据量文件操作的扩展

POSI TI ON po s l
几种 不 同 情 况 的 处 理 方 法 。
境为 3 2 位 Wi n d o ws 系统 。
( 1 ) 首 先 我 们 把 需 要 操 作 的 数 据 文 件 时 文件F i l e l C o p y 。
并 且 还 要 针 对 一 些 数 据 结 构 不 能 操 作 大 型 格 式 的 大 数 据 量 文 件 的操 作 , 分 别 阐述 了 内存空间, 系 统 无 法 分配 内存 , 从 而导 致
m —f i 1 e.O P e n (f i 1 e N a m e,
中没 有考 虑 到大 数据 量 的 可能 性 , 对数 据块 i f ( mmf . Ma p F i l e ( t e mp Na me , TRU E, 大 小 的描 述 都 是 采 用 的整 型i n t 型或 长 整 型 F I L E ~ S HA R E — RE A D) )
信 息技 术
VC6. 0在 3 2位机 中对 大数 据量 文件 操作 的扩 展
褚 晓 冬 ( 中海 油 田服务股 份有 限公 司油 田技术研 究 院 河北 燕郊
0 6 5 2 0 1 )
摘 要 : 目前 , 随 着计算 机在 各个 产 业部 门的逐 渐普 及 、 计算机 运算 能 力的逐 步提 高 以及各 种新 型需 求的诞 生 , 对文 件存 储 以及访 问 的需求也 随之 升高 , 人 们已经不 能满足 于基 于兆叛 的数据文 件的 访问 , 更大 的数 据文 件的访 问和 支持 能 力对开 发人 员提 出 了更 高的要 求, 但是 , 受计算 机硬 件 条件 , 系统软 件 的版 本 以及软 件 开发 版本 的 约束 , 我 们并 不 能大 刀 阔斧的 对软 件进 行彻 底修 改 , 否则会 对软 件的兼容 性遗 成非 常 严重 的危 害 , 因此 我们 需要针 对不 同情 况来 分剐对 各种 大型数据进 行遍 历 , 从 而保 证软件 在不 同配置 的计算机 上
基于VC++的海量图像分割

B P文件结构 的内容这里不再赘述。 M
下 面将 给 出 成 员 变 量 定 义 , 四个 重 要 的外 部 接 口 函数 和 四
个 内存 成员 函数的详细代码和 注释 ,限于篇幅 ,其他 函数和代
码 不再 叙述 ,可 以参 看 源 程 序 。 t 成 员变 量定 义 . c s S lDb p biC be t l s pi i: u l O jc a C t c
{
p o e t d rt ce :
、
分 析
利用 内存映射文件实现海量文件 ,其机理 实际上 是应用 了
一
种 自定义 的内存 映射机制 ,将硬 盘上 的数 据地址通 过某 种特
定 的映 射 方 式 映 射 到 某 个 虚 拟 的 内存 地 址 ,整 个 硬 盘 数 据 地 址 都 可 以 通 过 这 种 映 射 方 式 映 射 到 某 个 虚 拟 内存 地 址 区域 ,这 样
BIM AP I E ADER% m _ Bi a FlHe d r T F L HE p t p i m e a e;
/ 原始图像文件 头 /
BIM AP NF T I OHE ADE m _ Bt a lf He d r R p i pn o a e ; m
贝到指定 的内存 中进行处理 ,这个过程必然需要将数据从硬盘
处理海量 图像程序设计 中,一个 常用 的方法是使用 内存 映
射文件 ,但笔者在开发过程 中发现 ,内存 映射文件应用不 当,
有 可 能 引 起 内存 耗 尽 现 象 ,所 以撰 写 此 文 ,详 细 叙 述 了现 象 的 原 委 和 解 决 办 法 ,并 设 计 了一 个 可 用 于 海 量 图像 分 割 的类 ,给 出 了 一 个海 量 图像 分 割 的实 例 。
VC6.0在32位机中对大数据量文件操作的扩展

VC6.0在32位机中对大数据量文件操作的扩展摘要:目前,随着计算机在各个产业部门的逐渐普及、计算机运算能力的逐步提高以及各种新型需求的诞生,对文件存储以及访问的需求也随之升高,人们已经不能满足于基于兆级的数据文件的访问,更大的数据文件的访问和支持能力对开发人员提出了更高的要求,但是,受计算机硬件条件、系统软件的版本以及软件开发版本的约束,我们并不能大刀阔斧的对软件进行彻底修改,否则会对软件的兼容性造成非常严重的危害,因此我们需要针对不同情况来分别对各种大型数据进行遍历,从而保证软件在不同配置的计算机上能够顺利运行。
关键词:新型需求彻底修改遍历引言:在石油及矿产勘探领域,经常使用不同方式对地层进行探测,随着探测手段日益增强,衍生出的数据量也越来越大,从早期的几十兆到现在的几个G的级别,不仅对计算机的要求日益提高,同时对软件开发人员也提出了更高的要求:开发人员要花费大量精力来优化内存以及CPU的使用,并且还要针对一些数据结构不能操作大型数据进行扩展。
本文针对某油田测井数据格式的大数据量文件的操作,分别阐述了几种不同情况的处理方法。
本程序是基于VC6.0开发的,其运行环境为32位Windows系统。
1 修改数据描述格式:首先,我们需要面对的是数据格式不能满足需求的问题,对所有标识文件数据块大小的字段进行类型的修改,原有的代码中没有考虑到大数据量的可能性,对数据块大小的描述都是采用的整型int型或长整型long格式,由于采用的是有符号整型,所以其只能标识-2147483648~2147483648的文件块大小,这对于一般的线性数据块大小是足够的,但是对于大范围的波列数据以及矩阵类型数据的描述就捉襟见肘了。
本程序采用了一种叫做ULONGLONG的据格式,该格式为无符号64位数据格式,理论上可以达到0~18446744073709551616的存储长度,这样的话对于任意可能存在的数据长度,该格式都是足够描述的。
windows 读取超大文件到内存的方法

windows 读取超大文件到内存的方法以Windows读取超大文件到内存的方法在日常的计算机使用过程中,我们经常会遇到需要读取超大文件的情况。
然而,由于超大文件的体积过大,直接将其读取到内存中可能会导致内存溢出或系统崩溃的问题。
本文将介绍一种在Windows系统下读取超大文件到内存的方法,以避免出现这些问题。
一、使用流式读取在处理超大文件时,我们可以使用流式读取的方式,逐行读取文件内容,而不是一次性将整个文件读入内存。
这种方式可以大大减少内存的占用,提高程序的运行效率。
在Windows系统下,我们可以使用Python编程语言来实现流式读取超大文件的操作。
首先,我们需要安装Python的相关环境。
然后,使用以下代码来实现文件的流式读取:```pythonwith open('file.txt', 'r') as file:for line in file:# 处理每一行的代码```这段代码中,我们使用`open()`函数打开文件,并以只读模式(`'r'`)读取文件内容。
然后,通过`for`循环逐行读取文件内容,并在每一行进行相应的处理。
通过这种方式,我们可以将超大文件的内容逐行读取到内存中,而不会占用过多的内存空间。
二、使用缓冲区除了流式读取,我们还可以使用缓冲区的方式来读取超大文件。
缓冲区是一种临时存储区域,可以将部分文件内容读入内存,然后逐步处理。
这样可以减少对内存的占用,提高读取文件的效率。
在Windows系统下,我们可以使用C#编程语言来实现使用缓冲区读取超大文件的操作。
首先,我们需要在代码中引入`System.IO`命名空间。
然后,使用以下代码来实现文件的缓冲区读取:```csharpusing (var fileStream = new FileStream("file.txt", FileMode.Open)){using (var streamReader = new StreamReader(fileStream, Encoding.UTF8, true, 1024)){while (!streamReader.EndOfStream){var line = streamReader.ReadLine();// 处理每一行的代码}}}```这段代码中,我们使用`FileStream`和`StreamReader`类来实现文件的缓冲区读取。
内存映射文件与共享内存的区别

内存映射文件与共享内存的区别
内存映射文件和共享内存都是用来实现进程间通信的技术,但它们之间存在着
一些重要的区别。
首先,内存映射文件是将一个文件映射到进程的地址空间中,使得整个文件可以像内存一样被访问,而共享内存则是将一段物理内存映射到多个进程的地址空间中,以实现进程间数据的共享。
其次,内存映射文件是一种将文件内容映射到内存的技术,通过将文件映射到
内存中,可以避免频繁的磁盘IO操作,提高访问文件内容的速度。
而共享内存则
是一段物理内存空间,在不同进程中访问共享内存可以实现进程间的数据共享,比如可以通过共享内存传递数据或共享某些资源。
另外,内存映射文件是一种通过对文件进行映射来实现内存访问的技术,对文
件的修改会实时反映到文件中,但内存映射文件不支持对文件进行完全随机的访问和修改。
而共享内存是一种直接访问物理内存的方式,对共享内存的操作会直接影响到进程间的通信。
此外,内存映射文件更适用于对文件进行读写操作,特别是适合大文件的处理,而共享内存更适用于简单的数据共享,比如进程之间传递一些共享的数据结构或缓冲区。
综上所述,内存映射文件和共享内存都是实现进程间通信的方式,但它们在实
现机制、适用场景和操作方式上存在一些区别。
开发者可以根据具体的需求选择合适的技术来实现进程间通信,提高程序的性能和效率。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) { TRACE("创建文件对象失败,错误代码:%d\r\n", GetLastError()); return; } // 创建文件映射对象 HANDLE hFileMap = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 0, NULL); if (hFileMap == NULL) { TRACE("创建文件映射对象失败,错误代码:%d\r\n", GetLastError()); return; } // 得到系统分配粒度 SYSTEM_INFO SysInfo; GetSystemInfo(&SysInfo); DWORD dwGran = SysInfo.dwAllocationGranularity; // 得到文件尺寸 DWORD dwFileSizeHigh; __int64 qwFileSize = GetFileSize(hFile, &dwFileSizeHigh); qwFileSize |= (((__int64)dwFileSizeHigh) << 32); // 关闭文件对象 CloseHandle(hFile); // 偏移地址 __int64 qwFileOffset = 0; // 块大小 DWORD dwBlockBytes = dwGran; while (qwFileSize > 0) { // 映射视图 if (qwFileSize < dwGran) dwBlockBytes = (DWORD)qwFileSize; LPBYTE lpbMapAddress = (LPBYTE)MapViewOfFile(hFileMap,FILE_MAP_ALL_ACCESS, (DWORD)(qwFileOffset >> 32), (DWORD)(qwFileOffset & 0xFFFFFFFF), dwBlockBytes); if (lpbMapAddress == NULL) { TRACE("映射文件映射失败,错误代码:%d\r\n", GetLastError()); return; } // 对映射的视图进行访问 for(DWORD i = 0; i < dwBlockBytes; i++) {
静态、动态数据,一旦对它们的操作被提交,这些页面也将被备份至系统的页面文件,这与可执 行文件被用来备份执行代码页面的过程是很类似的。 图 1 展示了代码页面和数据页面在磁盘存储 器上的备份过程: 图 1 进程的代码页、数据页在磁盘存储器上的备份 显然,如果可以采取同一种方式来处理代码和数据页面,无疑将会提高程序的执行效率,而 内存映射文件的使用恰恰可以满足此需求。
下面分别对这些关键函数进行说明: 1)CreateFile():CreateFile()函数是一个用途非常广泛的函数,在这里的用法并没 有什么特殊的地方,但有几点需要注意:一是访问模式参数 dwDesiredAccess。该参数设置了对 文件内核对象的访问类型,其允许设置的权限可以为读权限 GENERIC_READ、写权限 GENERIC_WRITE、读写权限 GENERIC_READ | GENERIC_WRITE 和设备查询权限 0。在使用映射文件 时,只能打开那些具有可读访问权限的文件,即只能应用 GENERIC_READ 和 GENERIC_READ | GENERIC_WRITE 这两种组合;另一点需要注意的是共享模式参数 dwShareMode。该参数定义了对 文件内核对象的共享方式,其可能的设置为 FILE_SHARE_READ、FILE_SHARE_WRITE 和 0,并可对 其组合使用。其中,设置为 0 时不允许共享对象; FILE_SHARE_READ 和 FILE_SHARE_WRITE 分别 为在要求只读、只写访问的情况下才允许对象的共享。 由于通过内存映射文件可以在多个进程间共享数据,因此在进行这种应用时应当考虑 dwShareMode 参数设置对运行结果的影响。 2)CreateFileMapping():该函数的作用是创建一个文件映射内核对象,以告知系统文件 映射对象需要多大的物理存储器。 创建内存映射文件对象对系统资源几乎没有什么影响, 也不会 影响进程的虚拟地址空间。 除了需要用来表示该对象的内部资源之外通常并不用为其分配虚拟内 存, 但是如果内存映射文件对象是作共享内存之用的话, 就要在创建对象时由系统为内存映射文 件的使用在系统页文件中保留足够的空间。 函数第一个参数 hFile 为标识要映射到进程的地址空间的文件的句柄。 虽然由于内存映射文
BYTE temp = *(lpbMapAddress + i); } // 撤消文件映像 UnmapViewOfFile(lpbMapAddress); // 修正参数 qwFileOffset += dwBlockBytes; qwFileSize -= dwBlockBytes; } // 关闭文件映射对象句柄 CloseHandle(hFileMap); AfxMessageBox("成功完成对文件的访问"); } 在本例中,首先通过 GetFileSize()得到被处理文件长度(64 位)的高 32 位和低 32 位值。 然后在映射过程中设定每次映射的块大小为 1000 倍的分配粒度,如果文件长度小于 1000 倍的 分配粒度时则将块大小设置为文件的实际长度。在处理过程中由映射、访问、撤消映射构成了一 个循环处理。其中,每处理完一个文件块后都通过关闭文件映射对象来对每个文件块进行整理。 CreateFileMapping()、MapViewOfFile()等函数是专门用来进行内存文件映射处理用的。
VC 利用内存映射文件处理大文件(转载)
摘要: 本文通过内存映射文件的使用来对大尺寸文件进行访问操作, 同时也对内存映射文件的相 关概念和一般编程过程作了较为详细的介绍。 关键词:内存映射文件;大文件处理;分配粒度 引言 文件操作是应用程序最为基本的功能之一,Win32 API 和 MFC 均提供有支持文件处理的函数 和类,常用的有 Win32 API 的 CreateFile()、WriteFile()、ReadFile()和 MFC 提供的 CFile 类 等。一般来说,以上这些函数可以满足大多数场合的要求,但是对于某些特殊应用领域所需要的 动辄几十 GB、几百 GB、乃至几 TB 的海量存储,再以通常的文件处理方法进行处理显然是行不通 的。目前,对于上述这种大文件的操作一般是以内存映射文件的方式来加以处理的,本文下面将 针对这种 Windows 核心编程技术展开讨论。 内存映射文件概述 内存文件映射也是 Windows 的一种内存管理方法, 提供了一个统一的内存管理特征, 使应用 程序可以通过内存指针对磁盘上的文件进行访问, 其过程就如同对加载了文件的内存的访问。 通 过文件映射这种使磁盘文件的全部或部分内容与进程虚拟地址空间的某个区域建立映射关联的 能力, 可以直接对被映射的文件进行访问, 而不必执行文件 I/O 操作也无需对文件内容进行缓冲 处理。内存文件映射的这种特性是非常适合于用来管理大尺寸文件的。 在使用内存映射文件进行 I/O 处理时, 系统对数据的传输按页面来进行。 至于内部的所有内 存页面则是由虚拟内存管理器来负责管理, 由其来决定内存页面何时被分页到磁盘, 哪些页面应 该被释放以便为其它进程提供空闲空间, 以及每个进程可以拥有超出实际分配物理内存之外的多 少个页面空间等等。 由于虚拟内存管理器是以一种统一的方式来处理所有磁盘 I/O 的 (以页面为 单位对内存数据进行读写),因此这种优化使其有能力以足够快的速度来处理内存操作。 使用内存映射文件时所进行的任何实际 I/O 交互都是在内存中进行并以标准的内存地址形 式来访问。 磁盘的周期性分页也是由操作系统在后台隐蔽实现的, 对应用程序而言是完全透明的。 内存映射文件的这种特性在进行大文件的磁盘事务操作时将获得很高的效益。 需要说明的是,在系统的正常的分页操作过程中,内存映射文件并非一成不变的,它将被定 期更新。如果系统要使用的页面目前正被某个内存映射文件所占用,系统将释放此页面,如果页 面数据尚未保存,系统将在释放页面之前自动完成页面数据到磁盘的写入。 对于使用页虚拟存储管理的 Windows 操作系统, 内存映射文件是其内部已有的内存管理组件 的一个扩充。 由可执行代码页面和数据页面组成的应用程序可根据需要由操作系统来将这些页面 换进或换出内存。 如果内存中的某个页面不再需要, 操作系统将撤消此页面原拥用者对它的控制 权,并释放该页面以供其它进程使用。只有在该页面再次成为需求页面时,才会从磁盘上的可执 行文件重新读入内存。同样地,当一个进程初始化启动时,内存的页面将用来存储该应用程序的
件的物理存储器是来自于磁盘上的文件, 而非系统的页文件, 使创建内存映射文件就像保留一个 地址空间区域并将物理存储器提交给该区域一样。第二个参数为指向文件映射内核对象的 SECURITY_ATTRIBUTES 结构的指针,由此来决定子进程能否继承得到返回的句柄。通常为其传递 NULL 值,以默认的安全属性来禁止返回句柄的被继承。 接下来的参数用于文件被映射后设定文件映像的保护属性。其可能的取值为 PAGE_READONLY、 PAGE_READWRITE 和 PAGE_WRITECOPY。虽然在创建文件映射对象时,系统并不 为其保留地址空间区域,也不将文件的存储器映射到该区域。但是,在系统将存储器映射到进程 的地址空间中去时,系统必须确切知道应赋予物理存储器页面的保护属性。在设置保护属性时, 必须与用 CreateFile()函数打开文件时所指定的访问标识相匹配,否则将导致 CreateFileMapping()的执行失败。因此这里设置 PAGE_READWRITE 属性。除了上述三个页面 保护属性外,还有 4 个区(Section)保护属性也可以一起组合使用: