分块内存映射处理大文件-例子
参考 :http://user.qzone.qq.com/382164370/infocenter#!app=2&via=QZ.HashRefresh&pos=1363445766
内存映射文件可以用于3个不同的目的
• 系统使用内存映射文件,以便加载和执行. exe和DLL文件。这可以大大节省页文件空间和应用程序启动运行所需的时间。
• 可以使用内存映射文件来访问磁盘上的数据文件。这使你可以不必对文件执行I/O操作,并且可以不必对文件内容进行缓存。
• 可以使用内存映射文件,使同一台计算机上运行的多个进程能够相互之间共享数据。Windows确实提供了其他一些方法,以便在进程之间进行数据通信,但是这些方法都是使用内存映射文件来实现的,这使得内存映射文件成为单个计算机上的多个进程互相进行通信的最有效的方法。
使用内存映射数据文件
若要使用内存映射文件,必须执行下列操作步骤:
1) 创建或打开一个文件内核对象,该对象用于标识磁盘上你想用作内存映射文件的文件。
2) 创建一个文件映射内核对象,告诉系统该文件的大小和你打算如何访问该文件。
3) 让系统将文件映射对象的全部或一部分映射到你的进程地址空间中。
当完成对内存映射文件的使用时,必须执行下面这些步骤将它清除:
1) 告诉系统从你的进程的地址空间中撤消文件映射内核对象的映像。
2) 关闭文件映射内核对象。
3) 关闭文件内核对象。
文件操作是应用程序最为基本的功能之一,Win32 API和MFC均提供有支持文件处理的函数和类,常用的有Win32 API的CreateFile()、WriteFile()、ReadFile()和MFC提供的CFile类等。一般来说,以上这些函数可以满足大多数场合的要求,但是对于某些特殊应用领域所需要的动辄几十GB、几百GB、乃至几TB的海量存储,再以通常的文件处理方法进行处理显然是行不通的。所以可以使用内存文件映射来处理数据,网上也有铺天盖地的文章,但是映射大文件的时候又往往会出错,需要进行文件分块内存映射,这里就是这样的一个例子,教你如何把文件分块映射到内存。
//
// 该函数用于读取从CCD摄像头采集来的RAW视频数据当中的某一帧图像,
// RAW视频前596字节为头部信息,可以从其中读出视频总的帧数,
// 帧格式为1024*576*8
/*
参数:pszPath:文件名dwFrame: 要读取第几帧,默认读取第2帧
*/
BOOL MyFreeImage::LoadXRFrames(TCHAR *pszPath, DWORD dwFrame/* = 2*/ )
{// get the frames of X-Ray framesBOOL bLoop = TRUE;int i;int width = 1024;int height = 576;int bitcount = 8; //1, 4, 8, 24, 32////Build bitmap headerBITMAPFILEHEADER bitmapFileHeader; BITMAPINFOHEADER bitmapInfoHeader; BYTE rgbquad[4]; // RGBQUADint index = 0;DWORD widthbytes = ((bitcount*width + 31)/32)*4; //每行都是4的倍数 DWORD的倍数 这里是 576-TRACE1("widthbytes=%d\n", widthbytes);switch(bitcount) { case 1: index = 2; bitmapFileHeader.bfOffBits = (DWORD)(sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + 2*4); break; case 4: index = 16; bitmapFileHeader.bfOffBits = (DWORD)(sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + 16*4); break; case 8: index = 256; bitmapFileHeader.bfOffBits = (DWORD)(sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + 256*sizeof(RGBQUAD)); break; case 24: case 32: index = 0; bitmapFileHeader.bfOffBits = (DWORD)(sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)); break; default:break;} //构造Bitmap文件头BITMAPFILEHEADER bitmapFileHeader.bfType = 0x4d42; // 很重要的标志位 BM 标识bitmapFileHeader.bfSize = (DWORD)(bitmapFileHeader.bfOffBits + height * widthbytes); //bmp文件长度 bitmapFileHeader.bfReserved1 = 0; bitmapFileHeader.bfReserved2 = 0; //构造Bitmap文件信息头BITMAPINFOHEADER bitmapInfoHeader.biSize = sizeof(BITMAPINFOHEADER); bitmapInfoHeader.biWidth = width; bitmapInfoHeader.biHeight = height; bitmapInfoHeader.biPlanes = 1; bitmapInfoHeader.biBitCount = bitcount;bitmapInfoHeader.biCompression = BI_RGB; // 未压缩bitmapInfoHeader.biSizeImage = height * widthbytes; bitmapInfoHeader.biXPelsPerMeter = 3780; bitmapInfoHeader.biYPelsPerMeter = 3780; bitmapInfoHeader.biClrUsed = 0; bitmapInfoHeader.biClrImportant = 0; //创建BMP内存映像,写入位图头部BYTE *pMyBmp = new BYTE[bitmapFileHeader.bfSize]; // 我的位图pMyBmpBYTE *curr = pMyBmp; // curr指针指示pMyBmp的位置memset(curr, 0, bitmapFileHeader.bfSize); //写入头信息 memcpy(curr, &bitmapFileHeader,sizeof(BITMAPFILEHEADER));curr = pMyBmp + sizeof(BITMAPFILEHEADER); memcpy(curr, &bitmapInfoHeader,sizeof(BITMAPINFOHEADER)); curr += sizeof(BITMAPINFOHEADER);//构造调色板 , 当像素大于8位时,就没有调色板了。if(bitcount == 8) {rgbquad[3] = 0; //rgbReservedfor(i = 0; i < index; i++) { rgbquad[0] = rgbquad[1] = rgbquad[2] = i; memcpy(curr, rgbquad, sizeof(RGBQUAD)); curr += sizeof(RGBQUAD); } }else if(bitcount == 1) { rgbquad[3] = 0; //rgbReservedfor(i = 0; i < index; i++) { rgbquad[0] = rgbquad[1] = rgbquad[2] = (256 - i)%256; memcpy(curr, rgbquad, sizeof(RGBQUAD)); curr += sizeof(RGBQUAD); } } //// 文件映射,从文件中查找图像的数据//Open the real file on the file systemHANDLE hFile = CreateFile(pszPath, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);if (hFile == INVALID_HANDLE_VALUE){DWORD dwError = GetLastError();ATLTRACE(_T("MapFile, Failed in call to CreateFile, Error:%d\n"), dwError);SetLastError(dwError);bLoop = FALSE;return FALSE;}//Create the file mapping objectHANDLE hMapping = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 0, NULL);if (hMapping == NULL){DWORD dwError = GetLastError();ATLTRACE(_T("MapFile, Failed in call to CreateFileMapping, Error:%d\n"), dwError);// Close handleif (hFile != INVALID_HANDLE_VALUE){CloseHandle(hFile);hFile = INVALID_HANDLE_VALUE;}SetLastError(dwError);bLoop = FALSE;return FALSE;}// Retrieve allocation granularitySYSTEM_INFO sinf;GetSystemInfo(&sinf);DWORD dwAllocationGranularity = sinf.dwAllocationGranularity;// Retrieve file size// Retrieve file sizeDWORD dwFileSizeHigh;__int64 qwFileSize = GetFileSize(hFile, &dwFileSizeHigh);qwFileSize |= (((__int64)dwFileSizeHigh) << 32);CloseHandle(hFile);// Read Image__int64 qwFileOffset = 0; // 偏移地址DWORD dwBytesInBlock = 0, // 映射的块大小dwStandardBlock = 100* dwAllocationGranularity ; // 标准块大小DWORD dwFrameSize = height*width; // 计算一帧图像的数据量,不包括头部信息DWORD dwCurrentFrame = 1;dwBytesInBlock = dwStandardBlock;if (qwFileSize < dwStandardBlock)dwBytesInBlock = (DWORD)qwFileSize;//Map the view LPVOID lpData = MapViewOfFile(hMapping, FILE_MAP_ALL_ACCESS, static_cast<DWORD>((qwFileOffset & 0xFFFFFFFF00000000) >> 32), static_cast<DWORD>(qwFileOffset & 0xFFFFFFFF), dwBytesInBlock);if (lpData == NULL){DWORD dwError = GetLastError();ATLTRACE(_T("MapFile, Failed in call to MapViewOfFile, Error:%d\n"), dwError);// Close Handleif (hMapping != NULL){CloseHandle(hMapping);hMapping = NULL;}SetLastError(dwError);bLoop = FALSE;return FALSE;}BYTE *lpBits = (BYTE *)lpData;BYTE *curr1, *curr2, *lpEnd;curr1 = lpBits; // seek to startcurr2 = lpBits + 596; // seek to first framelpEnd = lpBits + dwBytesInBlock; // seek to end// Read video infomationKMemDataStream streamData( curr1, dwBytesInBlock);ReadXRHeader(streamData);while(bLoop){DWORD dwTmp = lpEnd - curr2; //内存缓冲剩余的字节if ( dwTmp >= dwFrameSize ) {if(dwCurrentFrame == dwFrame){memcpy(curr, curr2, dwFrameSize);bLoop = FALSE;}curr2 += dwFrameSize;}else //内存中不够一帧数据{DWORD dwTmp2 = dwFrameSize - dwTmp; // 一副完整的帧还需要dwTmp2字节if (dwCurrentFrame == dwFrame){memcpy(curr, curr2, dwTmp);curr += dwTmp;}
//1、首先计算文件的偏移位置
qwFileOffset += dwBytesInBlock;
//2、 检查还可以映射多少字节的东东到内存里面if ( qwFileSize - qwFileOffset < dwStandardBlock)dwBytesInBlock = (DWORD)(qwFileSize - qwFileOffset);//3、重新映射文件UnmapViewOfFile(lpData);lpData = MapViewOfFile(hMapping, FILE_MAP_ALL_ACCESS, static_cast<DWORD>((qwFileOffset & 0xFFFFFFFF00000000) >> 32), static_cast<DWORD>(qwFileOffset & 0xFFFFFFFF), dwBytesInBlock);if (lpData == NULL) // 一定要检查,不然可能内存映射失败{DWORD dwError = GetLastError();ATLTRACE(_T("MapFile, Failed in call to MapViewOfFile, Error:%d\n"), dwError);SetLastError(dwError);bLoop = FALSE;break;}curr2 = lpBits = (BYTE *)lpData;lpEnd = lpBits + dwBytesInBlock; // seek to endif (dwCurrentFrame == dwFrame){memcpy(curr, curr2, dwTmp2);bLoop = FALSE;}curr2 += dwTmp2;}dwCurrentFrame++;if (dwCurrentFrame > ((LPKINFO)m_VideoInfoHeader)->frames ) // 到达文件末尾{bLoop = FALSE;}}//将内存流 pMyBmp 转为bitmapKMemDataStream stream(pMyBmp, bitmapFileHeader.bfSize, true);if(!LoadFromMemory(FIF_BMP, stream))return FALSE;//if (lpData != NULL){//FlushViewOfFile(lpData, 0);UnmapViewOfFile(lpData);lpData = NULL;}//remove the file mappingif (hMapping != NULL){CloseHandle(hMapping);hMapping = NULL;}return TRUE;}
分块内存映射处理大文件-例子相关推荐
- c++ 利用内存映射读取大文件
由于用到的txt存放的数据有几十万行,用getline来读取文件非常慢,搜索了一下可以来优化读取文件的方法. 据说用内存映射读取文件速度快,试了一下,但是发现要分行处理数据时,速度还是挺慢的. 有关内 ...
- java 提交的内存_Java使用内存映射实现大文件的上传
在处理大文件时,如果利用普通的FileInputStream 或者FileOutputStream 抑或RandomAccessFile 来进行频繁的读写操作,都将导致进程因频繁读写外存而降低速度.如 ...
- 内存映射处理大文件[转载]
首先通过GetFileSize()得到被处理文件长度(64位)的高32位和低32位值.然后在映射过程中设定每次映射的块大小为1000倍的分配粒度(系统的数据分块大小),如果文件长度小于1000倍的分配 ...
- PHP几个快速读取大文件例子
PHP几个快速读取大文件例子 感谢 把我给崩了 的投递 时间:2014-10-16 来源:三联 在PHP中,对于文件的读取时,最快捷的方式莫过于使用一些诸如file.file_get_contents ...
- wcf服务器上传文件大小限制,wcf 上传大文件例子(亲测通过)
[实例简介] 亲测可以上传 300M的大文件,如果想上传更大的文件 请按照此链接提示做配置修改即可 http://www.cnblogs.com/duanweishi/p/5408395.html P ...
- 大文件存储引擎的实现与解析
1.大文件系统背景 对于需要存储大量数据的平台,数据不可能只保存在普通的单个文件或单台服务器中. 原因: EMC高端存储一台上百万元,但是两台也才不到一百个T,07年以前高端小型存储,后去IOE化(以 ...
- 【JavaNIO的深入研究4】内存映射文件I/O,大文件读写操作,Java nio之MappedByteBuffer,高效文件/内存映射...
内存映射文件能让你创建和修改那些因为太大而无法放入内存的文件.有了内存映射文件,你就可以认为文件已经全部读进了内存,然后把它当成一个非常大的数组来访问.这种解决办法能大大简化修改文件的代码. file ...
- system文件_大文件拷贝,试试NIO的内存映射
最近项目里有个需求需要实现文件拷贝,在java中文件拷贝流的读写,很容易就想到IO中的InputStream和OutputStream之类的,但是上网查了一下文件拷贝也是有很多种方法的,除了IO,还有 ...
- nio java 内核拷贝_大文件拷贝,试试NIO的内存映射
最近项目里有个需求需要实现文件拷贝,在java中文件拷贝流的读写,很容易就想到IO中的InputStream和OutputStream之类的,但是上网查了一下文件拷贝也是有很多种方法的,除了IO,还有 ...
最新文章
- MediaWiki安装
- EntityFramework用法探索(一)DatabaseFirst
- 上市公司相关财务指标
- 【Android 逆向】ART 脱壳 ( dex2oat 脱壳 | aosp 中搜索 dex2oat 源码 | dex2oat.cc#main 主函数源码 )
- 制作Scary爬虫步骤
- HDU 3641 Treasure Hunting(阶乘素因子分解+二分)
- java中遍历collection_使用Java中的Iterator遍历Collection
- 极光推送java服务器端_极光推送服务器端(JAVA)
- 03-Axure9默认元件库
- Android 银行账号
- MySQL常用SQL语句大全
- python 移动平均函数_python – NumPy版本的“指数加权移动平均线...
- GC日志详解[乐乐独记]
- 淘宝直播商品识别大赛
- python mongodb分页查询_python数据库分页查询语句
- redis—redis概述
- 聚观早报|中国将是ChatGPT主要对手;​iPhone 15将使用USB-C接口
- 爬虫Traceback (most recent call last):异常
- 谷歌浏览器恐龙游戏开挂秘诀
- vue前端下载文件的2种方式
热门文章
- Windows性能分析器概述(三)
- ASP.NET 2.0:如何让DropDownList同时拥有数据来源项目与自订项目 (转自章立民CnBlogs)...
- ionic android 版本号,ionic android 版本release 和 签名(示例代码)
- linux clone线程,如何在Linux上使用clone()创建真正的线程?
- java docx转html实例_Java实现将word转换为html的方法示例【doc与docx格式】
- python如何绘制曲线图_python pandas plot画折线图如何显示x轴的值?
- 同事操作两个数据源保持事务一致_「微服务架构」微服务架构中的数据一致性...
- nRF51822 SDK初体验
- java配置文件放置到jar外_java相关:Spring Boot 把配置文件和日志文件放到jar外部...
- VISIO2010界面介绍