使用 Windows 内存映射文件 (MMF) 的简单文件 I/O






4.24/5 (12投票s)
一个通用的 C++ 类,用于简单的文件 I/O,就像 CFile 一样。
引言
内存映射文件用于三种不同的目的
- 在两个不同的进程之间共享数据。
- 访问磁盘文件上的数据(使用内存映射文件访问磁盘文件上的数据可以屏蔽用户维护缓冲区的细节)。
- 系统使用 MMF 加载和执行 .exe 和 .dll 文件。
本文演示了使用内存映射文件的简单且通用的磁盘文件 I/O。
类 CWinMMFIO
是一个通用的 C++ 类,可以用于任何需要文件读取和写入操作的地方。该类封装了 MMF I/O 函数调用的细节。此类非常适合读取跨越数 GB 的大型文件。
已经观察到,与使用 CFile
或 fstream
对象相比,使用 MMF I/O 的读取/写入操作速度更快。
背景
理解和修改代码需要Windows内存管理概念的基础知识。
使用代码
以下是该类的公共接口
/* Construction */
bool Open(const rstring& strfile, OPENFLAGS oflags);
bool Close();
/* I/O */
int Read(void* pBuf, quint nCount);
int Write(void* pBuf, quint nCount);
/* Position */
suint64 Seek(sint64 lOffset, SEEKPOS eseekpos);
suint64 GetPosition();
/* Length */
suint64 GetLength();
bool SetLength(const sint64& nLength);
/*error*/
void GetMMFLastError(rstring& strErr);scription
接口描述
bool Open(const rstring& strfile, OPENFLAGS oflags);
以参数 oflags
中定义的访问模式打开文件 strfile
; OPENFLAGS
枚举器有两个常量,OPN_READ
和 OPN_READWRITE
。 零字节文件不能被打开进行读取或写入。
bool Close();
取消映射文件的视图,并关闭到文件映射对象和打开文件的打开的 HANDLE
。
int Read(void* pBuf, quint nCount);
将 nCount
个字节数读取到缓冲区 pBuf
中;如果 nCount
个字节数不可用,则 Read
从当前位置到文件末尾读取尽可能多的可用字节。
调用者必须确保缓冲区 pBuf
至少是 nCount
个字节宽。 该函数返回实际读取的字节数。 如果当前文件指针位置位于文件末尾且 nCount
大于零,则 Read
返回零。
int Write(void* pBuf, quint nCount);
将 nCount
个字节数从 pBuf
写入到从当前文件指针位置开始的文件。 每当尝试写入超过文件末尾时,文件大小将按 64KB 的量增加。 此长度由 LONG
内部变量 m_lExtendOnWriteLength
定义。 必要时,文件将恢复到其实际长度。
suint64 Seek(sint64 lOffset, SEEKPOS eseekpos);
将当前文件指针设置为相对于 SEEKPOS eseekpos
的 lOffset
指定的位置。 SEEKPOS
枚举器具有三个常量 SP_BEGIN
、SP_CUR
和 SP_END
。 SP_BEGIN
指定查找相对于文件开头。 SP_CUR
指定查找相对于当前文件指针。 SP_END
指定查找相对于文件末尾。
suint64 GetPosition();
返回当前文件指针位置
suint64 GetLength();
返回文件的实际长度(以字节为单位)
bool SetLength(const sint64& nLength);
将文件的长度设置为 nLength
字节。 如果无法设置长度,则返回值将为 false
。 调用 GetMMFLastError
以获取错误消息。
void GetMMFLastError(rstring& strErr);
当函数失败时,调用 GetMMFLastError
以字符串形式获取错误消息。
关注点
Windows SDK 函数 WriteFile
允许调用者通过根据需要扩展文件大小来写入超过 EOF 的内容。 此功能在内存映射 I/O 中不可直接使用。 为了写入并将文件扩展到当前 EOF 之外,需要取消映射视图并且必须关闭映射对象。 之后,使用 SetEndOfFile
函数扩展文件大小(例如,64K),重新创建映射对象,并重新映射文件。 只要写操作完成,文件必须恢复到其实际长度。
历史
- 2009 年 6 月 12 日:提交的第一个版本。