关于内存映射文件技术处理大文件的读写

使用ReadFile函数读取文件(C/C++) 在C/C++编程中,要读取文件的内容,可以使用Windows API中的ReadFile函数。在以上代码中,我们使用ReadFile函数读取文件的内容。在以上代码中,我们使用GetFileSize函数获取文件的大小,并将其存储在变量dwFileSize中。请确保在运行代码之前,将文件名修改为实际存在的文件名,并将代码放置在合适的C/C++项目中进行编译和运行。在以上代码中,我们使用CloseHandle函数关闭文件句柄,以释放对文件的访问。现在,我们可以使用ReadFile函数来实际读取文件的内容了。 阅读详情

Windows对文件的读写提供了很丰富的操作手段,如:
1. FILE *fp, fstearm...; (C/C++)
2. CFile, CStdioFile...; (MFC)
3. CreateFile, ReadFile...;(API)
...

在处理一般的文件(文本/非文本),这些足够了。然而在处理比较大的文件如
几十M, 几百M, 甚至上G的文件, 这时再用一般手段处理,系统就显的力不从心了

要把文件读出,再写进,耗费的是CPU利用率与内存以及IO的频繁操作。这显然是
令用户难以忍受的

为了解决这个吃内存,占CPU,以及IO瓶颈,windows核心编程提供了内存映射文件技术
(Maping File)

至于Maping File是什么原理,我不多说了,网上转载资源一箩筐,我只想从应用层
来考虑,怎样用这个技术,实现日常项目中的应用
举例来说:
可能项目中,会经常用到一些大量的常量,而这些大量常量用宏来替代写再源文件中
显然不可取,一般是写在文件中,给常量一些编号,通过编号来索引

一般文件比较小时候,常用做法也是先预读到内存中,毕竟从内存中读比从文件中读要快(IO操作的瓶颈)
比较好的做法,读到STL MAP 中去:
例如一个索引文件:
SEU07201213=汪洋中的一片叶子
JIANGSHENG=蒋晟
SEU07201214=优快云
............

打开文件,解析=号,在解析方面有
CString操作,strtok,strstr, boost 正则表达式匹配等等,但我比较喜欢
sscanf(szIndex, "%[^=]=%[^=]", sName, sValue);
sscanf(szIndex, "%[^=]=%s", sName, sValue);
fscanf(stream, "%[^=]=%[^=]", sName, sValue);

之类,
然后再定义一个map:
map<string, string> m_Map;
m_Map[sName] = sValue;

但是文件比较大的时候,笔者做过测试,用上面方法处理一个15M, 25万行的文本文件,占用内存非常
的高,达70多M,处理的速度也非常的慢,这还不包括回写到文件
这时,Maping File就派上用场了,这里处理大文件就抛弃了map的应用(因为容器占用很多内存)
而是直接利用字符指针来操作,不用其他封装,不多说了,请看示例:

 

#pragma warning(disable: 4786) 
#include 
<windows.h>
#include 
<stdio.h>
#include 
<iostream>
#include 
<string>

using namespace std;

string GetValue(const TCHAR *, const TCHAR *);  //根据name得value
void main(int argc, char* argv[])
{
    
// 创建文件对象(C: est.tsr)
    HANDLE hFile = CreateFile("C:/test.tsr", GENERIC_READ | GENERIC_WRITE,
        
0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    
if (hFile == INVALID_HANDLE_VALUE)
    
{
        printf(
"创建文件对象失败,错误代码:%d ", GetLastError());
        
return;
    }

    
// 创建文件映射对象
    HANDLE hFileMap = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 0, NULL);
    
if (hFileMap == NULL)
    
{
        printf(
"创建文件映射对象失败,错误代码:%d ", GetLastError());
        
return;
    }

    
// 得到系统分配粒度
    SYSTEM_INFO SysInfo;
    GetSystemInfo(
&SysInfo);
    DWORD dwGran 
= SysInfo.dwAllocationGranularity;
    
// 得到文件尺寸
    DWORD dwFileSizeHigh;
    __int64 qwFileSize 
= GetFileSize(hFile, &dwFileSizeHigh);
    qwFileSize 
|= (((__int64)dwFileSizeHigh) << 32);
    
// 关闭文件对象
    CloseHandle(hFile);
    
// 偏移地址 
    __int64 qwFileOffset = 0;
    
// 块大小
    DWORD dwBlockBytes = 1000 * dwGran;
    
if (qwFileSize < 1000 * dwGran)
        dwBlockBytes 
= (DWORD)qwFileSize;
    
if (qwFileOffset >= 0)
    
{
        
// 映射视图
        TCHAR *lpbMapAddress = (TCHAR *)MapViewOfFile(hFileMap,FILE_MAP_ALL_ACCESS, 
            
0, 0,
            dwBlockBytes);
        
if (lpbMapAddress == NULL)
        
{
            printf(
"映射文件映射失败,错误代码:%d ", GetLastError());
            
return;
        }


        
//-----------------------访问数据开始-------------------------
        cout<<GetValue(lpbMapAddress,"SEU07201213")<<endl;
        getchar();
//-----------------------访问数据结束-------------------------        
    
        
// 撤销文件映像
        UnmapViewOfFile(lpbMapAddress);
    }

    
// 关闭文件映射对象句柄
    CloseHandle(hFileMap);    
}

string GetValue(const TCHAR *lpbMapAddress, const TCHAR *sName)
{
   string sValue;  // 存放 = 后面的value值
  TCHAR *p1 = NULL, *p2 = NULL; // 字符指针
  if((p1 = strstr(lpbMapAddress,sName)) != NULL) // 查找sName出现位置
  {
   if(p2 = strstr(p1,"/r/n")) *p2 = '/0'; // 查找"/r/n"(换行)出现位置
   sValue = p1+strlen(sName)+strlen("="); // 指针移动"sName"+"="之后
   *p2 = '/r';  // 还原*p2值,因为不还原会改变原文件结构
  }
  return sValue;
}

 

以上实现了根据索引name匹配value的简单过程,经测试,同样25W行文件,匹配耗费1秒不到,且
不占本进程内存。
以上修改lpbMapAddress任意处值,也不需要重新回写到文件,真正是大大提高了文件读与写的效率
C语言之文件读写探究(三):fputs、fgets、feof(一次读写一行字符(文本操作)) 行的定义   行是文本编辑器中的概念,文件流中就是一个字符。这个在不同的平台是有差异的。window平台’\r\n’,linux平台是’\n’。 平台差异   windows平台在写入’\n’是会体现为’’,linux平台在写入’\n’时会体现为’\n’。windows平台在读入’\r\n’时,体现为一个字符’\n’,linux平台在读入’\n’时,体现为一个字符’\n’。   linux读windows中的换行,则会多读一个字符,windos读linux中的换行,则没有问题。 测试1:写入 测试2: f 阅读详情

相关推荐

虚拟机器人平台CoppeliaSim(Vrep)的逆运动学教学

相信看这篇博客的人都知道CoppeliaSim是做什么的,因此这里不多赘述。CoppeliaSim从最早的Vrep到现在已经更新了N个版本,从过去Vrep3.x开始使用的我这里小小地吐槽一下这个软件。CoppeliaSim每一个版本都有更新,问题是这些更新有时候不能向前兼容,而且时不时更新地让人不知所措(对于有紧急任务的时候真的很火大啊)。 以本文所展示地逆运动学来说,CoppeliaSim在4.0.0之后又大变,推翻了过往所有的拖动模块链接之类的构建方式,转而采用直接通过代码来实现逆运动学。 简单版逆运动

qq_39243015的博客 6698

window api 文件操作之CreateFile、ReadFile和WriteFile

​​​​​1. CreateFile   这个函数的功能是创建或者打开一个文件或者I/O设备,通常使用的I/O形式有文件、文件流、目录、物理磁盘、卷、终端流等。如执行成功,则返回文件句柄。 INVALID_HANDLE_VALUE 表示出错,会设置 GetLastError 。   函数的声明定义: HANDLE WINAPI CreateFile( _In_ LPCTSTR lpFileName, _In_ DWORD dwDesiredAccess, _In_ DWORD.

顺其自然~专栏 5373

稀疏变分高斯过程【超简单,全流程解析,案例应用,简单代码】

稀疏变分高斯过程(Sparse Variational Gaussian Processes, SVGP)是一种高效的高斯过程(GP)近似方法,它使用一组称为引入点的固定数据点来近似整个数据集。这种方法大大减少了高斯过程模型的计算复杂度,使其能够适用于大数据集。下面是SVGP的详细数学过程。在标准高斯过程中,给定数据集xiyii1N{(xi​yi​i1N​,目标是学习一个映射fff,其中f∼GPmkf∼GPmkmmm是均值函数,kkk。

刘文凯的博客 3658

CreateFile | ReadFile | WriteFile - WINDOWS API 第五弹 C++创建任意格式的文件用于读取和写入。

Windows api系列第五弹强烈来袭,本期介绍Windows上c++有关文件创建、读取和写入的api:CreateFile、ReadFile、WriteFile。

Bobowen的博客 5956

(实战)[re:Invent 2018]-001:赛道分析-(致敬1024)

打印log

Rainbow 2779

从转发时钟到嵌入式时钟:CDR、CTLE与DFE在高速串行链路中的协同演进

本文深入探讨了高速串行链路中CDR、CTLE与DFE技术的协同演进。从转发时钟到嵌入式时钟的转变,详细分析了CDR的工作原理与实现架构,以及CTLE和DFE在信道损耗补偿和ISI干扰消除中的关键作用。通过实战案例展示了这些技术在28Gbps至112Gbps SerDes设计中的优化策略与性能提升。

weixin_42539414的博客 294

[转][VC/MFC]关于内存映射文件技术处理大文件的读写-例

Windows对文件的读写提供了很丰富的操作手段,如: 1. FILE *fp, fstearm...; (C/C++) 2. CFile, CStdioFile...; (MFC) 3. CreateFile, ReadFile...;(API) ... 在处理一般的文件(文本/非文本),这些足够了。然而在处理比较大的文件如 几十M, 几百M, 甚至上G的文件, 这时再用一般手段处理,系统就显的力不从心了 要把文件读出,再写进,耗费的是CPU利用率与内存以及IO的频繁操作。这显然是

ssss5257的专栏 1546

CTF全能工具箱ProV2:集成AI与94GB离线资源库,打造无网环境下的智能解题流水线

CTF全能工具箱ProV2是一款专为线下CTF比赛设计的All-in-One离线解决方案。它集成了94GB的庞大离线资源库,涵盖Web、逆向、Pwn等全方向工具链与知识库,并创新性地内置了本地AI大模型,可在断网环境下提供智能解题辅助,实现从信息收集到漏洞利用的智能流水线作业,极大提升比赛效率。

weixin_29240343的博客 422

[转][VC/MFC]关于内存映射文件技术处理大文件的读写

Windows对文件的读写提供了很丰富的操作手段,如:1. FILE *fp, fstearm...; (C/C++)2. CFile, CStdioFile...; (MFC)3. CreateFile, ReadFile...;(API)...在处理一般的文件(文本/非文本),这些足够了。然而在处理比较大的文件如几十M, 几百M, 甚至上G的文件, 这时再用一般手段处理,系统就显的力不从心

believefym的专栏 1万+

从‘能看’到‘好看’:用Seaborn调色板让你的热力图在PPT和论文中脱颖而出

本文探讨如何利用Seaborn调色板提升热力图在PPT和论文中的视觉效果,从视觉心理学和场景适配角度出发,提供学术与商业场景下的配色方案和实战代码。通过优化色彩选择,使数据可视化更具专业性和吸引力,帮助读者快速理解关键信息。

weixin_30755393的博客 245

京东运维面试题及参考答案

cgroup(Control Group)是 Linux 内核提供的一种可以限制、控制与分离一个进程组群的资源(如 CPU、内存、磁盘 I/O 等)的机制。通过 cgroup,可以为不同的进程或进程组分配特定的资源配额,实现资源的隔离和管理。比如,在一个服务器上运行多个容器时,可以使用 cgroup 来限制每个容器对 CPU 和内存的使用,防止某个容器占用过多资源而影响其他容器的运行。cgroup 还可以对进程进行优先级设置,确保关键进程能够优先获得资源。

大模型大数据攻城狮的专栏 1236

【亲测免费】 高效处理大文件:Qt内存映射技术实战

高效处理大文件:Qt内存映射技术实战 【下载地址】Qt大文件读写内存映射资源文件 本仓库提供了一个名为“大文件读写内存映射.rar”的资源文件,该文件主要用于在Qt开发环境中实现大文件的读写操作,并利用内存映射技术提高文件操作的效率 ...

gitblog_09816的博客 1156

Python爬虫博客:如何抓取时事新闻信息 —— 从各大新闻网站获取实时新闻数据

发送请求:向目标新闻网站发送 HTTP 请求,获取网页内容。解析网页:使用解析库(如)从网页中提取新闻标题、摘要、内容、发布时间等。绕过反爬虫机制:使用代理、设置请求头、模拟浏览器行为等策略绕过反爬虫技术。数据存储与清洗:将抓取的数据保存到本地文件或数据库中,并进行清洗,确保数据的可用性。在抓取过程中,我们还会面对很多实际问题,比如反爬虫技术、分页抓取、动态加载的内容等。接下来,我们将逐步介绍如何使用不同技术抓取静态和动态网页,并对抓取的内容进行处理。Scrapy。

2201_76125261的博客 2135

Java中如何用内存映射处理大文件

在处理大文件时,如果利用普通的FileInputStream 或者FileOutputStream 抑或RandomAccessFile 来进行频繁的读写*作,都将导致进程因频繁读写外存而降低速度。   package test;   import java.io.BufferedInputStream;   import java.io.FileInputStream;

冥界执法者 540

温度PID控制PLC程序

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

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

使用内存映射文件加快文件操作速度

利用VB自身的文件处理命令,在对付几兆大小的文件时往往显得力不从心,速度慢得令人难以忍受。其实可以用一种方法将整个文件都读入内存,而不用一次又一次地访问磁盘。这个方法的实现可以通过多种方式。例如你可以将文件读入到一个Byte数组或一个字符串中,就象下面的代码一样: Public Function GetFileBytes (FileNa

lendalscut的专栏 2828

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

Java中用内存映射处理大文件

在处理大文件时,如果利用普通的FileInputStream 或者FileOutputStream 抑或RandomAccessFile 来进行频繁的读写操作,都将导致进程因频繁读写外存而降低速度.如下为一个对比实验。 [java] view plaincopy package test;      import java.io.Buffer

Geek Nero 849

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

java 内存映射处理大文件

Java中用内存映射处理大文件 在处理大文件时,如果利用普通的FileInputStream 或者FileOutputStream 抑或RandomAccessFile 来进行频繁的读写操作,都将导致进程因频繁读写外存而降低速度.如下为一个对比实验。 AD:

wguoyong的专栏 1414
上一篇: Install eda tools in ubuntu
下一篇: Ubuntu全程安装配置手册
AlfredLu
博客等级 码龄20年 16粉丝 19原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值