用Windows的文件映射机制,实现大批量数据的快速存储

JDOM库下载与XML处理技巧 JDOM是Java领域中一个处理XML文档的轻量级库,它提供了一个简单而直观的API来创建、操作和解析XML文件。与JAXB等重型库相比,JDOM更专注于XML的本质,易于理解和使用。JDOM的主要功能包括但不限于:快速构建XML文档、遍历和修改文档节点、添加和删除元素、以及执行Xpath查询等。它支持各种XML处理任务,使得Java开发者可以轻松地与XML文档交互。随着XML处理库在Java生态系统中的发展,JDOM也在不断地进化。 阅读详情

原文:http://blog.youkuaiyun.com/tonylk/archive/2006/05/11/725103.aspx

上次做的电子相册软件,为了解决大文件读取速度慢的问题,使用了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"

/*! /brief sampler::enstFileCache
     /author tony (http://www.tonixsoft.com)
     /version 0.08
     /date 2006.05.10
    
    基于文件镜像的快速大容量数据存储类。该类使用Windows下的 CreateFileMapping() 函数实现,不支持其它系统。/n
    该类中的文件镜像原理可以参考:http://www.juntuan.net/hkbc/winbc/n/2006-04-19/14320.html /n
    当要读取或写入的数据跨多个MapView的时候,该类会自动处理MapView的切换。
*/
class enstFileCache : public QObject
{
    Q_OBJECT

public:
    /*!
        construct the class.
    */
    enstFileCache();

    /*!
        destruct the class.
    */
    ~enstFileCache();

    /*!
        打开镜像文件。
        @return 当打开镜像文件失败时返回false,比如磁盘空间不够。
    */
    bool CreateFileCache(const QString &pFileName);

    /*!
        向镜像文件中追加数据。
    */
    bool AppendData(T_INT8* pData, int pDataLength);

    /*!
        从镜像文件的指定位置读取数据。
    */
    bool ReadData(T_INT64 pAddressOffset, T_INT8* pData, int pDataLength);

protected:
    void DumpWindowsErrorMessage();

private:
    T_INT64 mMappingViewSize;

    HANDLE mFileHandle;

    HANDLE mMappingHandle;

    T_INT64 mWriteMappingOffset;

    LPVOID mWriteBuffer;

    T_INT64 mWriteBufferOffset;

    T_INT64 mReadMappingOffset;

    LPVOID mReadBuffer;
};

#endif //enstfilecache_h

=====================================================

#include "enstfilecache.h"

#include "../enstsvcpack.h"

//#define FILE_CACHE_SIZE 0x40000000    /* = 1GB */
#define FILE_CACHE_SIZE 0x01E00000  /* = 30MB */

enstFileCache::enstFileCache()
{
    mMappingViewSize = 100*(64*1024); //window's default block size is 64KB

    mFileHandle = INVALID_HANDLE_VALUE;
    mMappingHandle = NULL;
    mWriteMappingOffset = 0;
    mWriteBuffer = NULL;
    mWriteBufferOffset = 0;
    mReadMappingOffset = 0;
    mReadBuffer = NULL;
}

enstFileCache::~enstFileCache()
{
    if (mWriteBuffer != NULL) {
        UnmapViewOfFile(mWriteBuffer);
    }
    if (mReadBuffer != NULL) {
        UnmapViewOfFile(mReadBuffer);
    }
    if (mMappingHandle != NULL) {
        CloseHandle(mMappingHandle);
    }
    if (mFileHandle != INVALID_HANDLE_VALUE) {
        CloseHandle(mFileHandle);
    }
}

bool enstFileCache::CreateFileCache(const QString &pFileName)
{
    enstLogService *logservice = enstLogService::GetMyAddr();

    mFileHandle = CreateFile(pFileName.toAscii(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
    if (mFileHandle == INVALID_HANDLE_VALUE) {
        DumpWindowsErrorMessage();
        logservice->AppendLog(this, "Error when create file.");
        return false;
    }
    mMappingHandle = CreateFileMapping(mFileHandle, NULL, PAGE_READWRITE, (DWORD)(FILE_CACHE_SIZE>>32), (DWORD)(FILE_CACHE_SIZE & 0xFFFFFFFF), NULL);
    if (mMappingHandle == NULL) {
        if (GetLastError() == 112) {
            logservice->AppendLog(this, "Looks like it's not enough space on the disk.");
        }
        DumpWindowsErrorMessage();
        logservice->AppendLog(this, "Error when create file mapping.");
        return false;
    }
    mWriteMappingOffset = 0;
    mWriteBuffer = NULL;
    mWriteBufferOffset = 0;
    mReadMappingOffset = 0;
    mReadBuffer = NULL;
    return true;
}

bool enstFileCache::AppendData(T_INT8* pData, int pDataLength)
{
    int datawrote = 0;
    do {
        int datacanwrite = mMappingViewSize - mWriteBufferOffset;
        if (mWriteBuffer && datacanwrite <= 0) {
            UnmapViewOfFile(mWriteBuffer);
            mWriteBuffer = NULL;
            mWriteMappingOffset += mMappingViewSize;
        }
        if (mWriteBuffer == NULL) {
            mWriteBuffer = MapViewOfFile(mMappingHandle, FILE_MAP_WRITE, (DWORD)(mWriteMappingOffset>>32), (DWORD)(mWriteMappingOffset & 0xFFFFFFFF), mMappingViewSize);
            mWriteBufferOffset = 0;
            datacanwrite = mMappingViewSize - mWriteBufferOffset;
            if (! mWriteBuffer) {
                DumpWindowsErrorMessage();
                enstLogService *logservice = enstLogService::GetMyAddr();
                logservice->AppendLog(this, "Error when map view of file.");
                return false;
            }
        }
        int datatowrite = pDataLength - datawrote;
        int actualdatatowrite = (datacanwrite >= datatowrite)?datatowrite:datacanwrite;
        memcpy((PBYTE)mWriteBuffer+mWriteBufferOffset, (PBYTE)pData+datawrote, actualdatatowrite);
        mWriteBufferOffset += actualdatatowrite;
        datawrote += actualdatatowrite;
    } while (datawrote < pDataLength);
    return true;
}

bool enstFileCache::ReadData(T_INT64 pAddressOffset, T_INT8* pData, int pDataLength)
{
    int datareaded = 0;
    do {
        int datacanread = mReadMappingOffset + mMappingViewSize - pAddressOffset - datareaded;
        if (mReadBuffer && (datacanread <= 0 || datacanread > mMappingViewSize)) {
            UnmapViewOfFile(mReadBuffer);
            mReadBuffer = NULL;
        }
        if (mReadBuffer == NULL) {
            mReadMappingOffset = (pAddressOffset + datareaded) / mMappingViewSize * mMappingViewSize;
            mReadBuffer = MapViewOfFile(mMappingHandle, FILE_MAP_READ, (DWORD)(mReadMappingOffset>>32), (DWORD)(mReadMappingOffset & 0xFFFFFFFF), mMappingViewSize);
            datacanread = mReadMappingOffset + mMappingViewSize - pAddressOffset - datareaded;
            if (! mReadBuffer) {
                DumpWindowsErrorMessage();
                enstLogService *logservice = enstLogService::GetMyAddr();
                logservice->AppendLog(this, "Error when map view of file.");
                return false;
            }
        }
        int datatoread = pDataLength - datareaded;
        int actualdatatoread = (datacanread >= datatoread)?datatoread:datacanread;
        memcpy((PBYTE)pData+datareaded, (PBYTE)mReadBuffer+pAddressOffset-mReadMappingOffset+datareaded, actualdatatoread);
        datareaded += actualdatatoread;
    } while (datareaded < pDataLength);
    return true;
}

void enstFileCache::DumpWindowsErrorMessage()
{
    LPVOID lpMsgBuf;
    DWORD dw = GetLastError();
    FormatMessage(
        FORMAT_MESSAGE_ALLOCATE_BUFFER |
        FORMAT_MESSAGE_FROM_SYSTEM,
        NULL,
        dw,
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
        (LPTSTR) &lpMsgBuf,
        0, NULL );
    enstLogService *logservice = enstLogService::GetMyAddr();
    logservice->AppendLog(this, (LPTSTR)lpMsgBuf);
    //puts((LPTSTR)lpMsgBuf);

    LocalFree(lpMsgBuf);
}

#ifdef WIN32
    #include "moc_enstfilecache.cpp"
#endif

由于系统是用QT开发的,因此类中使用了不少QT的类,同时也使用了系统中的部分工具类,不过基本工作原理相信你是能够看懂的。另外,整个系统是计划要跨平台使用的,因此今后还需要实现Linux下的类似功能,目前这个版本被绑定在Windows平台上了,不幸。

 

C++继承与多态 - 继承多态原理01 C++继承多态原理讲解 阅读详情

相关推荐

Clarity 3D Layout

Clarity 3D Layout Clarity 3D layout是3D 全波电磁场模型提取工具,它可以导入已经设计好的PCB文件也可以直接在Clarity 3D layout创建版图进行3D 全波电磁场模型提取。

m0_53280471的博客 5479

限制Map大小的实现方法

需求: 有时候需要往一个MAP中写入一些记录,但又怕无限制地写入会导致内存爆掉,所以得限制这个MAP的大小。 实现:LinkedHashMap提供了简单的方法。 首先,定义一个最大数,比如1000,然后new LinkedHashMap的时候,重写一下removeEldestEntry()方法: int maximumSize = 1000; LinkedHashMap myMap

Clement-Xu的专栏 1万+

CDD数据库文件制作(三)——服务配置(0x10)

根据诊断调查表进行每一步配置的详细操作,与背后逻辑解释 1.会话切换配置 1.1.根据诊断调查表进行信息提取(0x1001) 1.2.会话转换配置(0x1001) 1.3.根据诊断调查表进行信息提取(0x1002) 1.4.会话转换配置(0x1002) 1.5.根据诊断调查表进行信息提取(0x1003) 1.6.会话转换配置(0x1003) 1.7.会话切换配置完成后效果图 2.安全等级配置信息提取 2.1.安全访问配置(0x1001) 2.2.安全访问配置(0x1002) 2.3.安全访问配置(0x100

LOVE135149的博客 5838

内存映射文件(专门读写大文件)zz

引言 文件操作是应用程序最为基本的功能之一,Win32 API和MFC均提供有支持文件处理的函数和类,常用的有Win32 API的CreateFile()、WriteFile()、ReadFile()和MFC提供的CFile类等。一般来说,以上这些函数可以满足大多数场合的要求,但是对于某些特殊应用领域所需要的动辄几十GB、几百GB、乃至几TB的海量存储,再以通常的文件处理方法进行处理显然是行不通的。目前,对于上述这种大文件的操作一般是以内存映射文件的方式来加以处理的,本文下面将针对这种Window

东方未晞的老窝 1651

AUTOSAR MCAL开发及EB Tresos工具使用总结

在基于AutoSar CP架构开发MCAL时,会使用到EB tresos工具。本文主要对MCAL开发及EB tresos工具使用进行总结,仅作为自学使用,以方便后续查漏补缺。

liuxu324的博客 2626

基于深度学习的灰度图像气泡群识别与优化

灰度图像气泡群深度学习识别优化研究 本研究针对MATLAB实现的深度学习气泡群识别系统在从1445个点到4992个点扩展时出现的精度不稳定问题,提出了一套完整的解决方案。文章首先分析了问题根源,包括数据复杂度增加、类别不平衡、网络容量不足等因素,然后系统性地提出了数据预处理增强、网络架构优化、训练策略调整和后处理算法改进等优化措施。通过改进的U-Net架构、自适应直方图均衡化等技术创新,有效提升了模型在大规模气泡群图像上的识别精度和稳定性,为化工、生物医学等领域的灰度图像分析提供了可靠的技术支持。

max500600的博客 412

windows文件读取效率对比

readfile1.cpp是使用内存映射文件读取文件,readfile2.cpp是普通ReadFile readfile1.cpp代码 char buf[10001]; const char *env = getenv("LMS_TEST_DATA_DIR"); char wsp[255]; sprintf(wsp, "%s/shp_files/igis_big_te

liumengcheng的专栏 2821

【AIGC】Qwen3-Embedding:Embedding与Rerank模型新标杆

Qwen3-Embedding:文本嵌入与重排序模型的技术解析与应用实践

一个内容严谨、方向前沿、极具实践价值的AI大模型技术分享站 3089

Windows之内存映射文件

=====================Windows之内存映射文件===================== 几乎每个应用程序都要处理文件,但要处理好并不容易。应用程序到底是先应该打开文件、再读取文件,最后关闭文件呢,还是应该先打开文件,再用一个缓存算法来读取和写入 文件的不同部分?Windows为我们提供了一个两全其美的解决方案---内存映射文件。 内存映射文件允许开发人员预订一块地址

M-先生 795

CAN总线数据采集与分析

在CAN总线数据采集中,数据采集是指从CAN网络中获取数据,并将其存储在本地或远程数据库中。数据源:明确数据源,如CAN总线、CANoe/CANalyzer工具等。数据格式:确定数据格式,如CAN消息、信号值、环境变量等。数据存储:选择数据存储方式,如本地文件、数据库、云存储等。在CAN总线数据分析中,数据分析是指对采集到的数据进行处理和分析,以提取有用的信息。数据处理:对采集到的数据进行处理,如滤波、去噪、归一化等。数据分析:对处理后的数据进行分析,如统计分析、趋势分析、故障诊断等。数据可视化。

闲人编程的博客 4042

国债期货的日线趋势跟踪策略实现(基于backtrader框架)

通过backtrader框架,我们可以轻松地实现国债期货的日线趋势跟踪策略,并进行回测和验证。通过这种策略,我们可以尝试捕捉国债期货价格的短期趋势,并根据趋势的方向进行交易决策。backtrader提供了许多内置的指标、订单类型和其他功能,可以帮助你进一步优化和改进你的策略。它提供了丰富的工具和功能,使我们能够快速实现和验证我们的交易想法。方法中,我们根据当前价格和前一天的价格判断趋势的方向,并根据趋势的变化进行买入或卖出操作。然后,我们设置了初始资金和交易手续费,并将我们定义的策略。来跟踪每日的收盘价。

NisyPhilosophy的博客 404

JDOM的学习和使用

最近要把读出来的数据转换成xml文件,本来打算用dom4j,但是觉得那个太麻烦了,就来学习了一下JDOM.开始发觉学这个相当痛苦,主要是转换不成自己想要的格式,但是当自己去他官方网站上通过他给的例子就发现十分的简单了。 首先,我们要建立一个DOM树的根, 通过Element root = new Element("rootname")//其中rootname为你想要命名的根节点的值。 Doc...

iteye_17504的博客 188

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

Jdom

参考文献:JDom使用详解 http://www.javaresearch.org/article/showarticle.jsp?column=5&thread=23407

xxxuehao的专栏 763

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

JDOM和XPATH薛谷雨

XML是一种优秀的数据打包和数据交换的形式,在当今XML大行于天下,如果没有听说过它的大名,那可真是孤陋寡闻了。用XML描述数据的优势显而易见,它具有结构简单,便于人和机器阅读的双重功效,并弥补了关系型数据对客观世界中真实数据描述能力的不足。W3C组织根据技术领域的需要,制定出了XML的格式规范,并相应的建立了描述模型,简称DOM。各种流行的程序设计语言都纷纷根据这一模型推出了自己的XML解析...

weixin_34239169的博客 187

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

java jdom dom4j_实例分析jdom和dom4j的使用和区别

对于xml的解析和生成,我们在实际应用中用的比较多的是JDOM和DOM4J,下面通过例子来分析两者的区别(在这里我就不详细讲解怎么具体解析xml,如果对于xml的解析看不懂的可以先去看下我之前关于dom跟sax解析xml的随笔http://www.cnblogs.com/zhi-hao/p/3985720.html,其实理解了解析xml的原理,要想学习jdom跟dom4j就比较简单了,jdom跟d...

weixin_33873965的博客 556

jdom使用_提示,使用JDOM和XSLT

存档日期:2019年5月15日 | 首次发布:2001年3月1日 在本技巧中,Brett McLaughlin讲述了在使用XSLT和Java开发XML开发人员的JDOM API时如何避免常见的陷阱。 您将学习如何获取JDOM文档表示,如何使用Apache Xalan处理器对其进行转换,以及如何将生成的XML作为另一个JDOM文档获得。 使用XSLT转换文档是一项常见的任务,一旦您知道如何避...

cuyi7076的博客 151

jdom学习(5)在jdom中使用XPath(转)

  JDOM的关于XPATH的api在org.jdom.xpath这个包里。这个包下,有一个抽象类XPath.java和实现类JaxenXPath.java, 使用时先用XPath类的静态方法newInstance(String xpath)得到XPath对象,然后调用它的selectNodes(Object context)方法或selectSingleNode(Object context)方

明军的专栏 5785

JDOM使用详解

一、JDOM 简介JDOM是一个开源项目,它基于树型结构,利用纯JAVA的技术对XML文档实现解析、生成、序列化以及多种操作。JDOM 直接为JAVA编程服务。它利用更为强有力的JAVA语言的诸多特性(方法重载、集合概念以及映射),把SAX和DOM的功能有效地结合起来。在使用设计上尽可能地隐藏原来使用XML过程中的复杂性。利用JDOM处理XML文档将是一件轻松、简单的事。JDOM 在2000年

自强不息.厚德载物 2052

java org.jdom_Jdom使用指南

对xml文档的解析java中有很多种方法,例如使用dom、sax、jdom等等,相比之下,我觉得还是jdom比较方便。下面介绍一下jdom的基本使用方法,不对之处还请各位网友之交。谢谢!最新的jdom可以到他的网站:1.0版,下载之后将得到jdom-1.0.zip文件,解压后进入build文件夹将看到一个名为jdom.jar的包,这个就是jdom的类包了,将它加到你的classpath里就可以使用...

weixin_42198780的博客 2651

Jdom的使用方法!

对xml文档的解析java中有很多种方法,例如使用dom、sax、jdom等等,相比之下,我觉得还是jdom比较方便。下面介绍一下jdom的基本使用方法,不对之处还请各位网友之交。谢谢!最新的jdom可以到他的网站:http://www.jdom.org去下载,现在的版本是1.0版,下载之后将得到jdom-1.0.zip文件,解压后进入build文件夹将看到一个名为jdom.jar的包,这个就

CatJava.Net专栏 1424

JDOM 项目使用教程

JDOM 项目使用教程 1. 项目介绍 JDOM 是一个用于简化 Java 中 XML 操作的开源库。它提供了一种直观且易于使用的方式来处理 XML 文档,使得开发者能够更高效地读取、写入和修改 XML 数据。JDOM 的设计目标是让 Java 开发者能够以更自然的方式与 XML 交互,而不需要深入了解复杂的 XML 解析器。 JDOM 项目托管在 GitHub 上,地址为:https://git...

gitblog_00883的博客 502

jdom的使用

一、JDOM简介JDOM是一个开源项目,它基于树型结构,利用纯JAVA的技术对XML文档实现解析、生成、序列化以及多种操作。JDOM直接为JAVA编程服务。它利用更为强有力的JAVA语言的诸多特性(方法重载、集合概念以及映射),把SAX和DOM的功能有效地结合起来。在使用设计上尽可能地隐藏原来使用XML过程中的复杂性。利用JDOM处理XML文档将是一件轻松、简单的事。JDOM在2000年的春天被B

添天快乐(林-陈) 842

JDom使用详解

转自:https://blog.youkuaiyun.com/qq_27376871/article/details/53178366 【摘 要】JDOM是一个开源项目,它基于树型结构,利用纯JAVA的技术对XML文档实现解析、生成、序列化以及多种操作。 一、JDOM 简介 JDOM是一个开源项目,它基于树型结构,利用纯JAVA的技术对XML文档实现解析、生成、序列化以及多种操作。 JDOM 直接为J...

lalalalalala_的博客 898

java jdom 类_JDOM 介绍及使用指南

一、JDOM简介JDOM是一个开源项目,它基于树型结构,利用纯JAVA的技术对XML文档实现解析、生成、序列化以及多种操作。JDOM直接为JAVA编程服务。它利用更为强有力的JAVA语言的诸多特性(方法重载、集合概念以及映射),把SAX和DOM的功能有效地结合起来。在使用设计上尽可能地隐藏原来使用XML过程中的复杂性。利用JDOM处理XML文档将是一件轻松、简单的事。JDOM在2000年的春...

weixin_30679547的博客 1365

jdom使用举例

JAVAZHICHIZHE的专栏 547
上一篇: “Foxmail” 被遗忘的生活方式
下一篇: 优快云 韩磊 外传 【ALLyeSNO】
freexploit
博客等级 码龄22年 315粉丝 778原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值