c++/MFC 封装好的文件内存映射类
整理日: 2015年2月16日
首先介绍内存映射文件操作------函数的用法以及先后执行顺序
// 第一步:创建文件
HANDLE hFile = CreateFileForMapping(_T("MyMemFile.dat"), GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
ASSERT(hFile != 0);
// 第二步:创建内存映射文件对象
HANDLE hMapFile = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 1024,
_T("MyMapppingFile"));
ASSERT(hMapFile != 0);
// 第三步:获取内存映射文件对象视图
BYTE* pData = (BYTE*)MapViewOfFile(hMapFile, FILE_MAP_WRITE, 0, 0, 1024);
ASSERT(pData != NULL);
// 对 pData 指针进行读写操作
// ......
// 第四步:取消内存视图映射
UnmapViewOfFile(pData);
// 第五步:关闭内存映射对象句柄
CloseHandle(hMapFile);
// 第六步:关闭文件句柄
CloseHandle(hFile);
header file
// MapFile.h : header file
#if !defined(AFX_MAPFILE_H__D067E5C8_C4D7_4569_A6BB_9D651FB3F396__INCLUDED_)
#define AFX_MAPFILE_H__D067E5C8_C4D7_4569_A6BB_9D651FB3F396__INCLUDED_
#if _MSC_VER < 1000
#pragma once
#endif // _MSC_VER < 1000
/////////////////////////////////////////////////////////////////////////////
// CMapFile class 使用说明:
// 1 一个对象,打开文件映射之后,立即处理,处理完之后才能再用它打开另一个文件映射
class CMapFile
{
public:
CMapFile(); // protected constructor used by dynamic creation
virtual ~CMapFile();
// Attributes
PVOID m_pvFile;
BOOL m_bSmooth; // 为TRUE表示不阻塞,即不弹出任何对话框
private:
HANDLE hFileMap;
// Operations
public:
BOOL OpenMapFile(CString sFile);
// Implementation
BOOL CloseMapFile();
};
// {{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_MAPFILE_H__D067E5C8_C4D7_4569_A6BB_9D651FB3F396__INCLUDED_)
cpp file
// MapFile.cpp : implementation file
#include "stdafx.h"
#include "MapFile.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
// CMapFile
CMapFile::CMapFile()
{
m_pvFile = NULL;
m_bSmooth = FALSE;
}
CMapFile::~CMapFile()
{
if (NULL != m_pvFile)
{
UnmapViewOfFile(m_pvFile);
m_pvFile = NULL;
}
}
// CMapFile operation handlers
// 空文件会弹出 map could not be opened,在里面敲一个回车,就好了
BOOL CMapFile::OpenMapFile(CString sFile)
{
if (NULL != m_pvFile)
{
UnmapViewOfFile(m_pvFile); // 在当前应用程序的内存地址空间解除对一个文件映射对象的映射
m_pvFile = NULL;
}
// 1:创建或打开一个文件内核对象: Open the file for reading and writing.
// 这里CreateFile函数的参数,路径无论是否有空格都不能有引号,有引号的时候会出错。
HANDLE hFile = CreateFile(sFile, GENERIC_READ | GENERIC_WRITE, 0, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
// 由于hFile即使为INVALID_HANDLE_VALUE,下面的CreateFileMapping仍然可以正常运行,
// 所以这里一定要对hFile进行检查!
if (hFile == INVALID_HANDLE_VALUE)
{
if (!m_bSmooth) // 为TRUE表示不阻塞,即不弹出任何对话框
{
AfxMessageBox(_T("File[") + sFile +
_T("]could not be opened. Maybe it's not exist."));
}
return FALSE;
}
// 2:创建一个文件映射内核对象
DWORD dwFileSize = GetFileSize(hFile, NULL);
// 获取文件大小=文件长度+(WCHAR)'\0'(ssume the whole file can be mapped)
// Create the file-mapping object. The file-mapping object is 1 character
// bigger than the file size so that a zero character can be placed at the
// end of the file to terminate the string (file). Because I don't yet know
// if the file contains ANSI or Unicode characters, I assume worst case
// and add the size of a WCHAR instead of CHAR.
hFileMap = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, dwFileSize + 1,
/* sizeof(WCHAR)==2,sizeof(char)==1 */
// 因为我们要在文件的末尾加上一个字符串的结束符'\0', 当我们将这个文件映射到内存中时,
// 我们就可以像操作字符串一样地来操作文件了。
// 如果该文件小于设定的大小,本函数将扩展该文件的大小,使磁盘上的文件变大。
// 这样当以后将该文件作为内存映射 文件使用时,物理存储器就已经存在了。
NULL // 这个文件映射对象的名字用于与其他进程共享该对象,这里我们还用不到。
);
if (hFileMap == NULL)
{
if (!m_bSmooth)
{
AfxMessageBox(_T("File[") + sFile +
_T("] map could not be opened. May be it's empty."));
}
return FALSE;
}
// 3:将文件数据映射到进程的地址空间:
// 当创建了一个文件映射对象之后,仍然必须让系统为文件的数据保留一个地址空间区域,
// 并将文件的数据作为映射到该区域的物理存储器进行提交。
m_pvFile = MapViewOfFile(hFileMap, /* FILE_MAP_WRITE */ FILE_MAP_READ,
0, 0, 0); // 获取映射文件在内存中的首地址
// CloseHandle(hFileMap);// 关闭内存映射对象句柄
if (m_pvFile == NULL)
{
if (!m_bSmooth)
{
AfxMessageBox(_T("Could not map view of file[") + sFile + _T("]."));
}
return FALSE;
}
// 4:既然我们通过pvFile得到了映象视图的起始地址,那么可以对视图做一些操作了:
// ANSI版本:
// PSTR pchANSI = (PSTR) m_pvFile;
// UNICODE版本:
// PWSTR pchUnicode = (PWSTR) pvFile;如char* sz=(char*)m_pvFile;sz[dwFileSize/sizeof(char)]='\0';
// 5:从进程的地址空间中撤销文件数据的映象:
// UnmapViewOfFile(m_pvFile); // 封装为类,映象要在其他地方使用所以这句话要去掉
// 6:关闭文件映射对象和文件对象:
// CloseHandle(hFileMap);
// 我们改变了文件的长度,因此要重新设置文件的结束符以删除留在文件尾部的多余内容(比如删除我们先前加到文件末尾的'\0'字符)
SetFilePointer(hFile, dwFileSize, NULL, FILE_BEGIN);
SetEndOfFile(hFile); // 设定当前文件指针所在处为文件结束处.该处后面的内容将被删除
CloseHandle(hFile);
return TRUE;
}
BOOL CMapFile::CloseMapFile()
{
if (NULL != m_pvFile)
{
// 取消内存视图映射
if (UnmapViewOfFile(m_pvFile))
{
m_pvFile = NULL;
CloseHandle(hFileMap); // 关闭内存映射对象句柄
return TRUE;
}
return FALSE;
}
return TRUE;
}
c++/MFC 封装好的文件内存映射类的更多相关文章
- .NET Framework自带的文件内存映射类
最近一直为文件内存映射发愁,整个两周一直折腾这个东西.在64位系统和32位系统还要针对内存的高低位进行计算.好麻烦..还是没搞定 偶然从MSDN上发现.NET 4.0把内存文件映射加到了.NET类库中 ...
- MMAP文件内存映射
body, table{font-family: 微软雅黑; font-size: 10pt} table{border-collapse: collapse; border: solid gray; ...
- java大文件读写操作,java nio 之MappedByteBuffer,高效文件/内存映射
java处理大文件,一般用BufferedReader,BufferedInputStream这类带缓冲的Io类,不过如果文件超大的话,更快的方式是采用MappedByteBuffer. Mapped ...
- 使用CodeSmith快速生成映射文件和映射类
一 CodeSmith简介 本文以表自动生成NHibernate的映射文件和映射类的实例来说明一下本软件的使用方法. CodeSmith是一种基于模板的代码生成工具,其使用类似于ASP.NET的语法来 ...
- hibernate 的映射文件快速生成:使用CodeSmith快速生成映射文件和映射类
一 CodeSmith简介 本文以表自动生成NHibernate的映射文件和映射类的实例来说明一下本软件的使用方法. CodeSmith是一种基于模板的代码生成工具,其使用类似于ASP.NET的语法来 ...
- 【JavaNIO的深入研究4】内存映射文件I/O,大文件读写操作,Java nio之MappedByteBuffer,高效文件/内存映射
内存映射文件能让你创建和修改那些因为太大而无法放入内存的文件.有了内存映射文件,你就可以认为文件已经全部读进了内存,然后把它当成一个非常大的数组来访问.这种解决办法能大大简化修改文件的代码.fileC ...
- cocos2d 文件系统使用文件内存映射性能对比
//cocos 修改代码 ..... //性能测试代码 extern "C" { #include <time.h> #include <stdlib.h> ...
- windows内存映射学习及帮助类实现
本文通过创建文件内存映射类,学习windows内存映射相关知识:创建内存映射文件后,可以按照内存操作方式操作文件:支持32位程序处理超过4G大小的文件. 感谢http://blog.csdn.net/ ...
- 《Java核心技术卷二》笔记(二)文件操作和内存映射文件
文件操作 上一篇已经总结了流操作,其中也包括文件的读写.文件系统除了读写以为还有很多其他的操作,如复制.移动.删除.目录浏览.属性读写等.在Java7之前,一直使用File类用于文件的操作.Java7 ...
随机推荐
- Java用链表实现栈和队列
1.用链表实现栈 package stack; /** * * @author denghb * */ class Link { public long dData; public Link next ...
- C和指针 (pointers on C)——第四章:语句(上)
第四章--语句(上) 总结总结!!! C没有布尔类型,所以在一些逻辑推断时候必须用整型表达式,零值为假,非零值为真. for比while把控制循环的表达式收集起来放在一个地方,以便寻找. do语句比w ...
- iOS中保证线程安全的几种方式与性能对比
来源:景铭巴巴 链接:http://www.jianshu.com/p/938d68ed832c 一.前言 前段时间看了几个开源项目,发现他们保持线程同步的方式各不相同,有@synchronized. ...
- MySQL查询
DQL 操作 DQL 数据查询语言(重要) 数据库执行DQL语句不会对数据做出任何改变,而是让数据库发送结果集给客户端. 查询返回的结果是一张虚拟表. 查询关键字:SELECT ...
- 移动设备日期选择插件(基于JQUERY)
上周花了2个小时写的一个日期选择插件,比较适合移动端的设备.先看个效果图吧.如果刚好是你需要的就往下吧,不需要的也可以继续..... 其实网络上已经有的了类似的成熟插件,比如基于mobiscroll, ...
- Android开发必备:颜色选择
AA 指定透明度. 00 是完全透明. FF 是完全不透明.超出取值范围的值将被恢复为默认值. ffff00 ffff33 ffff66 ffff99 ffffcc ffffff ffcc0 ...
- JS事件监听 JS:attachEvent和addEventListener 使用方法
attachEvent与addEventListener区别适应的浏览器版本不同,同时在使用的过程中要注意attachEvent方法 按钮onclickaddEventListene ...
- javascript:console.log()是什么js库里的?
这个不是什么库的,这个是浏览器的函数,如果你使用firefox并且装有firebug插件,当使用console.log(……)时,会把括号内的字符串输出到控制台,当然,在IE中这个是没有的,要报错.相 ...
- CSS 组合选择符
CSS 组合选择符 组合选择符说明了两个选择器直接的关系. CSS组合选择符包括各种简单选择符的组合方式. 在 CSS3 中包含了四种组合方式: 后代选取器(以空格分隔) 子元素选择器(以大于号分隔) ...
- HTML网页图片滚动代码
<!--下面是向上滚动代码--> <div id=butong_net_top style=overflow:hidden;height:100;width:90;> < ...