VC中海量文件读写类设计与应用

文件操作是应用程序最为基本的功能之一,Win32 API和MFC均提供有支持文件处理的函数和类,常用的有Win32 API的CreateFile()、WriteFile()、ReadFile()和MFC提供的CFile类等。一般来说,以上这些函数可以满足大多数场合的要求,但是对于某些特殊应用领域所需要的动辄几十GB、几百GB、乃至几TB的海量存储,再以通常的文件处理方法进行处理显然是行不通的。目前,对于上述这种大文件的操作一般是以内存映射文件的方式来加以处理的,但它仅以Win32方式,提供了一组函数,使用起来很不方便,尤其是该方法使用起来,容易出现内存耗尽问题,基于此,本文设计了一个海量文件操作的类,可以对海量文件完成与CFile类相似的功能。

海量文件读写的一般方法

首先要通过CreateFile()函数来创建或打开一个文件内核对象,这个对象标识了磁盘上将要用作内存映射的文件。在用CreateFile()将文件映像在物理存储器的位置通告给操作系统后,只指定了映像文件的路径,映像的长度还没有指定。为了指定文件映射对象需要多大的物理存储空间,还需要通过CreateFileMapping()函数来创建一个文件映射内核对象,以告诉系统文件的尺寸以及访问文件的方式。在创建了文件映射对象后,还必须为文件数据保留一个地址空间区域,并把文件数据作为映射到该区域的物理存储器进行提交。由MapViewOfFile()函数负责通过系统的管理而将文件映射对象的全部或部分映射到进程地址空间。此时,对内存映射文件的使用和处理同通常加载到内存中的文件数据的处理方式基本一样,在完成了对内存映射文件的使用时,还要通过一系列的操作完成对其的清除和使用过资源的释放。这部分相对比较简单,可以通过UnmapViewOfFile()完成从进程的地址空间撤消文件数据的映像、通过CloseHandle()关闭前面创建的文件映射对象和文件对象。

存在问题和解决办法

利用内存映射文件实现海量文件,其机理实际上是应用了一种自己定义的内存映射机制,将硬盘上的数据地址通过某种特定的映射方式映射到某个虚拟的内存地址,整个硬盘数据地址都可以通过这种映射方式映射到某个虚拟内存地址区域,这样就可以像处理内存一样,处理硬盘数据。实际上,内存映射文件建立的初始阶段并没有为这些待处理的数据分配任何的内存,但是如果数据要得到处理,例如程序需要将某部分数据拷贝到指定的内存中进行处理,这个过程必然需要将数据从硬盘中读到与指定内存相独立的某个内存地址区域,然后才可能将这些数据从一块内存拷贝到另一块内存,在这个过程中,映射机制为处理的数据动态地分配了相应大小的内存。遗憾的是,不知道是出于何种考虑,映射机制没有动态释放这些动态分配的内存,也没有提供强制释放这些动态内存的函数,所以,随着程序遍历整个海量文件,动态分配的内存将与海量文件相当,出现内存耗尽现象。为了避免这种方法,笔者的方法是通过不断建立和撤消文件数据的映像,达到动态建立和释放内存的目的。

海量文件读写类设计

类一般包括两个部分:成员函数和成员变量,成员函数和成员变量又有公共、私有和保护之分。对于成员函数和成员变量,笔者浅显地认为,成员函数实际上是对一类对象的操作,而成员变量是与对象操作相适应的特性。一般公共函数和变量是类与其他类进行交流的外部接口,其他私有和保护成员,在没有继承的情况下,可以简单地认为是为了完成这些接口操作所有需要的内部变量和操作。对于文件读写操作而言,一般包括:文件打开,文件写,文件读,文件关闭,这些函数将作为类的公共成员函数,有时候外部类也需要获取文件特定偏移下的数据的虚拟地址,这个函数也作为公共成员函数。其他为实现外部操作,即公共成员函数的所有函数和变量都被设计为私有成员。由于对对象的同一种性质的操作,如文件读操作,可以有不同的方式,所以就需要对函数进行重载操作。在本类的设计中对文件打开,文件读,文件写都定义了多种重载操作。

成员函数和变量定义:将类取名为HugeFile,类的成员函数和成员变量定义如下:

class HugeFile

{

public:

HugeFile();

virtual ~HugeFile();

BOOL HFileCreate(CString sFilePath, DWORD dFileLength);

//文件打开,默认缓存大小

BOOL HFileOpen(CString sFilePath);

//文件打开,设置缓存大小

BOOL HFileOpen(CString sFilePath , DWORD dCL);

//改变缓存大小

void HSetCacheLength(DWORD dCL);

//文件读

BOOL HFileRead( LPBYTE lpDest, DWORD dLength );

void HFileClose();

//文件读,指定起始地址

BOOL HFileRead(LPBYTE lpDest, LPBYTE lpSource, DWORD dLength );

//文件读,指定偏移量

BOOL HFileRead(LPBYTE lpDest, DWORD dBytesOff, DWORD dLength);

//根据偏移量返回数据虚拟内存地址

LPVOID HSeekData( DWORD dBytesOff );

//文件写

BOOL HFileWrite( LPBYTE lpSource , DWORD dLength);

//文件写,指定目的地址

BOOL HFileWrite( LPBYTE lpSource , LPBYTE lpSource, DWORD dLength);

//文件写,指定偏移量

BOOL HFileWrite( LPBYTE lpSource , DWORD dBytesOff, DWORD dLength);

private:

BOOL HFileTry(DWORD dLength ); //试图动态释放内存

//根据操作起始地址和操作长度更新参数

void HRefreshWorkPara( LPBYTE lpStart, DWORD dLength);

//根据操作长度更新参数

void HRefreshWorkPara( DWORD dLength);

//根据偏移量和长度更新参数

void HRefreshWorkPara( DWORD dBytesOff, DWORD dLength);

private:

HANDLE m_hFile;     //文件句柄

HANDLE m_hFilemap;    //文件内存映射文件句柄

LPVOID m_lpvFile;    //文件数据指针

LPBYTE m_lpbWork;    //当前工作指向指针

DWORD m_dPreBytesOff;   //记录读数据偏移

DWORD m_dDataLength;   //文件打开后操作数据的长度

DWORD m_dCacheLength;   //缓存大小

public:

DWORD m_dFileSize;    //文件大小

CString m_sFileName;   //文件名称

}

VC中海量文件读写类设计与应用相关推荐

  1. VC中海量文件读写类设计与应用(转)

    VC中海量文件读写类设计与应用   沈瑞冰 摘要 本文阐述了海量文件读写的一般方法,并分析了该方法中存在的内存耗尽问题和解决办法,并就此设计了一个海量文件读写类,封装了海量文件读写操作,最后给出了一个 ...

  2. VC++中使用使用winnet类获取网页内容

    2005-09-01 VC++中使用使用winnet类获取网页内容 - [VC专栏] 微软提供的Winnet类是一个应用层的网络通信组件, 它可以使你的应用程序很容易的实现http.ftp.gophe ...

  3. 剖析VC中的文件操作

    剖析VC中的文件操作 2002-8-4 17:33:29   燕山大学   聂栋栋   阅读次数: 18539 各种关于文件的操作在程序设计中十分常见,如果能对这些操作都了如指掌,就可以根据实际情况找 ...

  4. [转]VC++中对文件的写入和读取

    本文转自:http://blog.csdn.net/fanghb_1984/article/details/7425705 本文介绍两种方法对文件进行读取和写入操作:1.采用fstream类:2.采用 ...

  5. Java生鲜电商平台-电商中海量搜索ElasticSearch架构设计实战与源码解析

    Java生鲜电商平台-电商中海量搜索ElasticSearch架构设计实战与源码解析 生鲜电商搜索引擎的特点 众所周知,标准的搜索引擎主要分成三个大的部分,第一步是爬虫系统,第二步是数据分析,第三步才 ...

  6. VC++中对文件的写入和读取

    VC++中对文件的写入和读取 本文介绍两种方法对文件进行读取和写入操作:1.采用fstream类:2.采用CStdioFile类. CStdioFile继承自CFile,一个CStdioFile对象代 ...

  7. verilog从txt中读取_verilog语言中的文件读写

    verilog语言中的文件读写 原创: IC控 IC控 2月22日 在Verilog语言中,对文件的读写一般用在编写testbench,而用到的系统函数大概有以下几种,首先是$fopen,然后是对文件 ...

  8. python中的文件读写操作

    python中的文件读写操作 思维导图 Python读写CSV文件 csv文件是什么? CSV(Comma Separated Values)全称逗号分隔值文件是一种简单.通用的文件格式,被广泛的应用 ...

  9. Java中同一个文件里类和方法的引用

    Java中同一个文件里类和方法的引用 在项目开发时往往需要在同一个文件里创建几个类,并互相引用,但小白们搞不懂,所以我给大家讲解一下 目录 Java中同一个文件里类和方法的引用 1.权限修饰符 2.类 ...

最新文章

  1. Windows禁止启动某个程序!偷偷禁止,别人就打不开。。。比如,微信 LOL 吃鸡 爱奇艺
  2. 【 Notes 】NLS ALGORITHMS of TOA - Based Positioning
  3. 什么原因导致挖掘机老自动熄火憋车熄火?
  4. html小球跳跃技术原理,弹跳的小球.html · web-project-songyu/原生js小例子 - Gitee.com...
  5. 区块链技术应用的关键问题和挑战
  6. 国外方案 组件化_网页webp解决方案
  7. linux 显示器分辨率设置太小了,显示器不显示 如何在设置回来,当“显示设置”中的分辨率不可用时,如何使用xrandr设置自定义分辨率...
  8. 【数组】 - 有序数组设计
  9. 【语义分割】ICCV21_Self-Regulation for Semantic Segmentation
  10. 面试系统设计_系统设计面试问题–您应该知道的概念
  11. Ubuntu linux上Nautilus安装RabbitVCS扩展
  12. oracle update范例,oracle 12c单范例数据库打12.1.0.2.4补丁记录
  13. Linux/UNIX 图形操作环境KDE 与GNOME
  14. 高中计算机技术教材,广西科学技术出版高中信息技术教材第一册《计算机硬件组成》...
  15. ROP攻击:Challenge 0x14: Horcruxes
  16. 从空运物流到无人机物流,圆通将战火烧到了时效件
  17. paip 破解网站手机验证码
  18. 谷歌浏览器控制台preview乱码问题及原因
  19. 【TA-霜狼_may-《百人计划》】图形3.4 延迟渲染管线介绍
  20. coc机器人苹果_警察机器人绳索英雄

热门文章

  1. kafka消息队列学习笔记
  2. Mybatis 源码分析(一)配置文件加载流程
  3. PL/SQL 12.0配置连接远程Oracle数据库
  4. GlusterFS分布式存储系统
  5. redis memcache 性能比较
  6. Python标准库--time模块的详解
  7. POJ - 1127 Jack Straws(几何)
  8. Android的post()方法究竟运行在哪个线程中
  9. [つづく]MySTL
  10. HTML5与CSS3权威指南.pdf7