`
hulianwang2014
  • 浏览: 686802 次
文章分类
社区版块
存档分类
最新评论
  • bcworld: 排版成这样,一点看的欲望都没有了
    jfinal

关于内存映射文件技术处理大文件的读写

 
阅读更多

Windows对文件的读写提供了很丰富的操作手段,如:
1. FILE *fp, fstearm...; (C/C++)
2. CFile, CStdioFile...; (MFC)
3. CreateFile, ReadFile...;(API)
...

在处理一般的文件(文本/非文本),这些足够了。然而在处理比较大的文件如
几十M, 几百M, 甚至上G的文件, 这时再用一般手段处理,系统就显的力不从心了

要把文件读出,再写进,耗费的是CPU利用率与内存以及IO的频繁操作。这显然是
令用户难以忍受的。

为了解决这个吃内存,占CPU,以及IO瓶颈,windows核心编程提供了内存映射文件技术(Maping File)。

至于Maping File是什么原理,我不多说了,网上转载资源一箩筐,我只想从应用层来考虑,怎样用这个技术,实现日常项目中的应用。
举例来说:
可能项目中,会经常用到一些大量的常量,而这些大量常量用宏来替代写再源文件中
显然不可取,一般是写在文件中,给常量一些编号,通过编号来索引

一般文件比较小时候,常用做法也是先预读到内存中,毕竟从内存中读比从文件中读要快(IO操作的瓶颈)
比较好的做法,读到STL MAP 中去:
例如一个索引文件:
SEU07201213=汪洋中的一片叶子
JIANGSHENG=蒋晟
SEU07201214=CSDN
............
打开文件,解析=号,在解析方面有CString操作,strtok,strstr, boost 正则表达式匹配等等,但我比较喜欢
sscanf(szIndex, "%[^=]=%[^=]", sName, sValue);
sscanf(szIndex, "%[^=]=%s", sName, sValue);
fscanf(stream, "%[^=]=%[^=]", sName, sValue);
之类,
然后再定义一个map:
map<string, string> m_Map;
m_Map[sName] = sValue;

但是文件比较大的时候,笔者做过测试,用上面方法处理一个15M, 25万行的文本文件,占用内存非常
的高,达70多M,处理的速度也非常的慢,这还不包括回写到文件
这时,Maping File就派上用场了,这里处理大文件就抛弃了map的应用(因为容器占用很多内存)
而是直接利用字符指针来操作,不用其他封装,不多说了,请看示例:

#pragmawarning(disable:4786)
#include
<windows.h>
#include
<stdio.h>
#include
<iostream>
#include
<string>

usingnamespacestd;

stringGetValue(constTCHAR*,constTCHAR*);//根据name得value
voidmain(intargc,char*argv[])
{
//创建文件对象(C:est.tsr)
HANDLEhFile=CreateFile("C: est.tsr",GENERIC_READ|GENERIC_WRITE,
0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
if(hFile==INVALID_HANDLE_VALUE)
...{
printf(
"创建文件对象失败,错误代码:%d",GetLastError());
return;
}
//创建文件映射对象
HANDLEhFileMap=CreateFileMapping(hFile,NULL,PAGE_READWRITE,0,0,NULL);
if(hFileMap==NULL)
...{
printf(
"创建文件映射对象失败,错误代码:%d",GetLastError());
return;
}
//得到系统分配粒度
SYSTEM_INFOSysInfo;
GetSystemInfo(
&SysInfo);
DWORDdwGran
=SysInfo.dwAllocationGranularity;
//得到文件尺寸
DWORDdwFileSizeHigh;
__int64qwFileSize
=GetFileSize(hFile,&dwFileSizeHigh);
qwFileSize
|=(((__int64)dwFileSizeHigh)<<32);
//关闭文件对象
CloseHandle(hFile);
//偏移地址
__int64qwFileOffset=0;
//块大小
DWORDdwBlockBytes=1000*dwGran;
if(qwFileSize<1000*dwGran)
dwBlockBytes
=(DWORD)qwFileSize;
if(qwFileOffset>=0)
...{
//映射视图
TCHAR*lpbMapAddress=(TCHAR*)MapViewOfFile(hFileMap,FILE_MAP_ALL_ACCESS,
0,0,
dwBlockBytes);
if(lpbMapAddress==NULL)
...{
printf(
"映射文件映射失败,错误代码:%d",GetLastError());
return;
}


//-----------------------访问数据开始-------------------------
cout<<GetValue(lpbMapAddress,"SEU07201213")<<endl;
getchar();
//-----------------------访问数据结束-------------------------

//撤销文件映像
UnmapViewOfFile(lpbMapAddress);
}
//关闭文件映射对象句柄
CloseHandle(hFileMap);
}
stringGetValue(constTCHAR*lpbMapAddress,constTCHAR*sName)
{
stringsValue;//存放=后面的value值
TCHAR*p1=NULL,*p2=NULL;//字符指针
if((p1=strstr(lpbMapAddress,sName))!=NULL)//查找sName出现位置
{
if(p2=strstr(p1," "))*p2='

以上实现了根据索引name匹配value的简单过程,经测试,同样25W行文件,匹配耗费1秒不到,且
不占本进程内存。
以上修改lpbMapAddress任意处值,也不需要重新回写到文件,真正是大大提高了文件读与写的效率

该文章转载自网络大本营:http://www.pushad.com/Info/13520.Html


相关:另一篇利用C#实现 http://www.libing.net.cn/read.php/1252.htm
分享到:
评论

相关推荐

    大文件读写内存映射.rar

    qt 内存 映射 大文件读写

    内存映射修改大文件_内存映射_MemoryFile_超大文件读写_

    实际工作中遇到超大文件读写时很多系统需要等待较长时间,给用户体验不佳。本文结合源码讲解了超大文件的内存映射读写方式。内存映射方式极大的提高了读写效率,提升用户体验感。

    内存映射读写文件的方法

    关于内存映射文件读写文件的方法,大家学习了解一下

    VC++中使用内存映射文件处理大文件

    了解VC++中,内存映射文件处理。其中讲述了令人头痛的内存映射问题

    易语言内存映射大文件

    易语言内存映射大文件源码,内存映射大文件,创建映射,打开文件_,取颗粒数,映射内存,读基址,释放内存,关闭文件_,写入字节集,移动读写位置_,读位置指针,删除字节集,十六到十,映射_创建,API_取文件长度,API_打开文件,API...

    内存映射方式读写文件

    使用内存映射的方式读写文件,提高文件读写速度

    共享内存(内存映射文件)封装类以及使用实例

    用内存映射文件实现的共享内存封装类。 实现了数据读写互斥。

    读写内存映射数据的代码

    一段读写内存映射数据的代码,对内存映射区域进行读写操作

    内存映射文件

    内存映射文件

    易语言大文件读写模块

    易语言大文件读写模块源码,大文件读写模块,初始化,取总行数,取行文本,条件查询

    内存映射文件使用方法.pdf

    解释内存映射的基本概念,以及读写文件生成文件等细节注意事项,另外文章中还有内存映射大文件的细节办法。需要进行初学内存映射的人非常适合学习。

    linux mmap文件内存映射机制

    它本身提供了不同于一般对普通文件的访问方式,进程可以像读写内存一样对普通文件的操作。而 Posix或系统V的共享内存IPC则纯粹用于共享目的,当然mmap()实现共享内存也是其主要应用之一。  mmap系统调用使得进程...

    内存映射I/O大文件性能测试代码

    内存映射I/O的读写性能测试,以内存映射I/O和和系统调用write写500M文件为例

    内存映射文件(VC)

    将文件内容映射到内存中的某个地址区域,然后可以直接操作内存来读写文 件,操作系统来负责处理数据的缓存,缓冲,写入和调入以及内存的分配和释放。 这样文件的输入和输出由操作系统来处理,可以提高应用程序的性能...

    VC++采用内存映射方式高效率读写大数据

    在有时候,项目的数据量特别大,而且源源不断的到来,这个时候,利用传统的IO文件流写文件势必效率很低跟不上节奏,这时候采用内存映射提高读写效率

    Python内存映射文件读写方式

    主要介绍了Python内存映射文件读写方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧

    内存映射的封装 包含读、写文件

    本代码 完美封装 好用易懂. 已在自己的项目中使用很久 稳定无bug, 内存映射的好处就不说了 但如果直接使用API 过程很繁复.

    易语言内存映射类模块

    易语言内存映射类模块源码,内存映射类模块,创建映射,打开文件_,取颗粒数,映射内存,读基址,释放内存,关闭文件_,写入字节集,移动读写位置_,读位置指针,删除字节集,映射_创建,关闭句柄,映射_置内存,写字节集,映射_释放...

    fmstream:对Windows和POSIX系统上的内存映射文件进行读写访问-开源

    fmstream提供了一个接口,可以从内存映射文件中读取数据作为输入/输出流。 文件映射是文件内容与进程的虚拟地址空间的一部分的关联。 系统创建文件映射对象(也称为节对象)以维护此关联。 文件视图是进程用来访问...

    Windows程序设计实验三.doc

    尝试修改教材246页8.4.2使用内存映射文件读BMP文件的例子,要求如下: 1、 读取并显示一张彩色的bmp文件; 2、 用鼠标左键的点击实现图片的放大功能,右键点击实现图片的缩小; 3、 鼠标左键按下拖动实现图片的随动...

Global site tag (gtag.js) - Google Analytics