中国IT动力,最新最全的IT技术教程
最新100篇 | 推荐100篇 | 专题100篇 | 排行榜 | 搜索 | 在线API文档 | 网通镜像
首 页 | 程序开发 | 操作系统 | 软件应用 | 图形图象 | 网络应用 | 精文荟萃 | 教育认证 | 硬件维护 | 未整理篇 | 站长教程
ASP JS PHP工程 ASP.NET 网站建设 UML J2EESUN .NET VC VB VFP 网络维护 数据库 DB2 SQL2000 Oracle Mysql
服务器 Win2000 Office C DreamWeaver FireWorks Flash PhotoShop 上网宝典 CorelDraw 协议大全 网络安全 微软认证
硬件维护  CPU  主板  硬盘  内存  显卡  显示器  键盘鼠标  声卡音箱  打印机  机箱电源  BIOS  网卡  C#  Java  Delphi  vs.net2005
  当前位置:> 程序开发 > 编程语言 > 综合其它
VC++中使用内存映射文件处理大文件(3)
作者:佚名 时间:2007-09-24 16:07 出处:中国电波传播研究所 责编:月夜寒箫
              摘要:VC++中使用内存映射文件处理大文件(3)

用内存映射文件处理大文件应用示例

下面结合一个具体的实例来进一步讲述内存映射文件的使用方法。该实例从端口接收数据,并实时将其存放于磁盘,由于数据量大(几十GB),在此选用内存映射文件进行处理。下面给出的是位于工作线程MainProc中的部分主要代码,该线程自程序运行时启动,当端口有数据到达时将会发出事件hEvent[0],WaitForMultipleObjects()函数等待到该事件发生后将接收到的数据保存到磁盘,如果终止接收将发出事件hEvent[1],事件处理过程将负责完成资源的释放和文件的关闭等工作。下面给出此线程处理函数的具体实现过程:

            

……

// 创建文件内核对象,其句柄保存于hFile

HANDLE hFile = CreateFile("Recv1.zip",

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);

while(bLoop)

{

// 捕获事件hEvent[0]和事件hEvent[1]

DWORD ret = WaitForMultipleObjects(2, hEvent, FALSE, INFINITE);

ret -= WAIT_OBJECT_0;

switch (ret)

{

// 接收数据事件触发

case 0:

// 从端口接收数据并保存到内存映射文件

nReadLen=syio_Read(port[1], pbFile + qwFileOffset, QueueLen);

qwFileOffset += nReadLen;

// 当数据写满60%时,为防数据溢出,需要在其后开辟一新的映射视图

if (qwFileOffset > T)

{

T = qwFileOffset + 600 * sinf.dwAllocationGranularity;

UnmapViewOfFile(pbFile);

pbFile = (PBYTE)MapViewOfFile(hFileMapping,

FILE_MAP_ALL_ACCESS,

(DWORD)(qwFileOffset>>32), (DWORD)(qwFileOffset&0xFFFFFFFF), dwBytesInBlock);

}

break;

// 终止事件触发

case 1:

bLoop = FALSE;

// 从进程的地址空间撤消文件数据映像

UnmapViewOfFile(pbFile);

// 关闭文件映射对象

CloseHandle(hFileMapping);

break;

}

}

在终止事件触发处理过程中如果只简单的执行UnmapViewOfFile()和CloseHandle()函数将无法正确标识文件的实际大小,即如果开辟的内存映射文件为30GB,而接收的数据只有14GB,那么上述程序执行完后,保存的文件长度仍是30GB。也就是说,在处理完成后还要再次通过内存映射文件的形式将文件恢复到实际大小,下面是实现此要求的主要代码:

            

// 创建另外一个文件内核对象

hFile2 = CreateFile("Recv.zip",

GENERIC_WRITE | GENERIC_READ,

FILE_SHARE_READ,

NULL,

CREATE_ALWAYS,

FILE_FLAG_SEQUENTIAL_SCAN,

NULL);

// 以实际数据长度创建另外一个文件映射内核对象

hFileMapping2 = CreateFileMapping(hFile2,

NULL,

PAGE_READWRITE,

0,

(DWORD)(qwFileOffset&0xFFFFFFFF),

NULL);

// 关闭文件内核对象

CloseHandle(hFile2);

// 将文件数据映射到进程的地址空间

pbFile2 = (PBYTE)MapViewOfFile(hFileMapping2,

FILE_MAP_ALL_ACCESS,

0, 0, qwFileOffset);

// 将数据从原来的内存映射文件复制到此内存映射文件

memcpy(pbFile2, pbFile, qwFileOffset);

file://从进程的地址空间撤消文件数据映像

UnmapViewOfFile(pbFile);

UnmapViewOfFile(pbFile2);

// 关闭文件映射对象

CloseHandle(hFileMapping);

CloseHandle(hFileMapping2);

// 删除临时文件

DeleteFile("Recv1.zip");

 结论

经实际测试,内存映射文件在处理大数据量文件时表现出了良好的性能,比通常使用CFile类和ReadFile()和WriteFile()等函数的文件处理方式具有明显的优势。本文所述代码在Windows 98下由Microsoft Visual C++ 6.0编译通过。

关闭本页
 
首页 | 投资与合作 | 服务条款 | 隐私政策 | 收藏本站 | 设为首页 | 新用户注册 | 免责声明 | 使用帮助
Copyright ©2005-2008 chinaitpower.com All rights reserved. www.chinaitpower.com 版权所有