用户操作
[即时聊天] [发私信] [加为好友]
虎0406ID:hu0406
17184次访问,排名6941好友2人,关注者2
苦心人,天不负,破釜沉舟,百二秦川终归蜀;有志者,事竟成,卧薪尝胆,三千越甲可吞吴。
hu0406的文章
原创 17 篇
翻译 0 篇
转载 40 篇
评论 13 篇
虎0406的公告
苦心人,天不负,破釜沉舟,百二秦川终归蜀;有志者,事竟成,卧薪尝胆,三千越甲可吞吴。
最近评论
呀呀:谢谢你的提供和劳动
边诗涵:谢谢
流星雨:太酷了,好有用啊!!!!!
爱情:太帅了 ,谢了
枫叶520:谢谢
文章分类
收藏
    相册
    My photo
    编程
    充电港湾
    codeProject
    Kevins
    MSDN
    VCer
    判官的Blog
    协议及相关
    开发者的乐园
    看雪学院
    老罗的缤纷天地
    邮件技术咨询网
    邹青峰野狼一个愚笨的程序员的成长之路
    技术Blog
    c0ffee1982的专栏
    stealthwalker
    西邮陈老师
    休闲小酌
    存档
    订阅我的博客
    XML聚合  FeedSky

    转载 VC++中使用内存映射文件处理大文件 (2)收藏

    新一篇: 消息钩子函数入门篇 | 旧一篇: VC++中使用内存映射文件处理大文件 (1)

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

    下面结合一个具体的实例来进一步讲述内存映射文件的使用方法。该实例从端口接收数 据,并实时将其存放于磁盘,由于数据量大(几十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编译通过。

     

    发表于 @ 2008年03月26日 22:05:00|评论(loading...)|编辑

    新一篇: 消息钩子函数入门篇 | 旧一篇: VC++中使用内存映射文件处理大文件 (1)

    评论:没有评论。

    发表评论  


    登录
    Csdn Blog version 3.1a
    Copyright © 虎0406