用Windows的文件映射机制,实现大批量数据的快速存储
上次做的 电子相册软件 ,为了解决大文件读取速度慢的问题,使用了Windows下的文件映射功能,使文件读取效率顿时得到了大幅度提升。(具体见: 一个读取速度超快的FileStream! )
最近在做的一款软件,又使用到了这个函数,不过这次的要求是这样的:
系统的主程序会持续的从网络端口上接收数据,这些数据需要变为实时的图像显示,但是同时图像显示部分又需要有回顾功能,也就是说能够任意将历史的数据调出来显示,为此就必须将所有历史数据保存下来,同时在需要的时候又能够快速从历史数据的指定位置将数据读出来。
针对此,有两种方案:
1)在主程序所在的机器接收数据前,使用另一台电脑,配合一个转发数据的程序,来达到数据的截取功能,由这个转发数据的程序将所有数据存储下来,并在主程序需要使用时,再用网络发送给主程序。
2)使用主程序来进行数据存储,提高主程序存储数据的性能。
不管采用何种方案,最终的瓶颈都将是大数据量的快速保存。由于整个系统内存使用和速度上的要求都很高,因此不可能将这样的数据放在程序内存里,也不可能使用普通的文件方式来记录数据。最终看来只有求助于Windows的文件映射功能了,它的优点是不会将要操作的文件读入内存,而是直接在系统层对文件进行读写,因此省去了文件的复制过程,特别是在读写大文件时,它能带来的速度提升是非常显著的。这样就可以将文件当作大内存来用了。
新的程序写完,才发现原来以前用Delphi实现的那个版本根本不能够访问大文件,只是在读取文件速度上有些优势而已,因为我过去的做法是在CreateFileMapping()之后,将整个文件的内存都MapViewOfFile()到程序内存里,这样文件一大,程序仍然无法打开文件。现在才知道,MapViewOfFile()函数是可以指定从文件的哪个部分进行Map,同时Map多少进入内存的。对于真正的大文件(几个G的)的访问,因该是一块一块的Map,然后进行读写。同时Map的起始地址和Map的内存大小都必须是64K的整数倍,不然MapViewOfFile()函数会失败。
最初的一个简单的程序版本花了1个小时不到就写完了,但是一测试却发现有个严重的问题:没有考虑数据在Map内存的边界上时的问题。当要读写的数据正好在Map的内存的边界上时,从当前Map的内存中就只能取到数据的前半部分,另一部分的数据必须Map文件的下一块地址才可能取到。因此对程序又进行了彻底的改造,让其能够在读取一个Map内存发现不够时,自动打开下一个Map内存。
总算大功告成,写了一个简单的测试程序对其进行测试,速度和正确性都都非常理想。 最后,贴上程序代码:
#ifndef enstfilecache_h
#define enstfilecache_h
#include <QtCore/QVariant>
#include <QtCore/QObject>
#include <windows.h>
#include "../enstdefine.h"
/*! rief sampler::enstFileCache
author tony (http://www.tonixsoft.com)
version 0.08
date 2006.05.10
- 上一篇:vc中如何使用设备描述表
- 下一篇:Visual C#程序员面试基础问题和答案