[VC]使用内存映射技术对文件进行倒序

Kilo Code跨端AI执行体:多环境安装与模型配置实操指南 Kilo Code并非传统AI编程插件,而是一种可编排的AI执行体,其核心在于将开发者意图转化为可验证、可降级、可审计的代码生成流程。它基于标准化环境契约(如Git配置、Python版本、Docker可用性)实现跨Windows/macOS/Ubuntu/WSL2等平台的一致行为,依托模型路由层与硬件约束感知机制,在本地算力与云端服务间智能调度。技术价值体现在降低AI生成代码的调试成本、提升CI/CD中AI能力的确定性交付,并支撑嵌入式、Web API、数据库交互等真实工程场景。本文聚焦六类典型环境下的零配 阅读详情

代码解释

对文件内容进行倒序的最容易的方法是调用C运行期函数_ strrev。与所有C字符串一样,字符串的最后一个字符必须是个0结束符。由于文本文件不以0为结束符,因此FileReverse必须给文件附加一个0。若要进行这样的附加操作,首先要调用GetFileSize函数:
// Get the size of the file (I assume the whole file can be mapped).
	DWORD dwFileSize = GetFileSize(hFile, NULL);
现在已经得到了文件的长度,你能够通过调用CreateFileMapping函数创建文件映射对象。创建的文件映射对象的长度是dwFileSize加一个宽字符的大小(对于0字符来说)。当文件映射对象创建后,该对象的视图就被映射到FileReverse的地址空间。变量pvFile包含了MapViewOfFile函数的返回值,并指向文本文件的第一个字节。
下一步是在文件的结尾处写一个0,并对字符串进行倒序:
		// 文件末尾添加 0,作为字符串的结束符
		PSTR pchANSI = (PSTR) pvFile;
		pchANSI[dwFileSize / sizeof(CHAR)] = 0;
在文本文件中,每一行的结尾都是一个回车符(‘\ r’)后随一个换行符(‘\ n’)。但是,当调用_strrev对文件进行倒序时,这些字符也会被倒序。如果将已经倒序的文本文件加载到文本编辑器,那么出现的每一对“ \ n \ r”字符都必须重新改为它的原始顺序。这个倒序操作是由下面的循环代码进行的:
while (pchANSI != NULL) {
			// We have found an occurrence....
			*pchANSI++ = '\r';   // Change '\n' to '\r'.
			*pchANSI++ = '\n';   // Change '\r' to '\n'.
			pchANSI = strstr(pchANSI, "\n\r"); // Find the next occurrence.
		}
当你观察这样一个简单的代码时,可能很容易忘记你实际上是在对磁盘驱动器上的文件内容进行操作(这显示出内存映射文件的功能是多么大)。
在文件被倒序后, FileReverse便进行清除操作,撤消文件映射对象的视图映象,关闭所有的内核对象句柄。此外,FileReverse必须删除附加给文件结尾处的0字符(记住_strrev并不对结尾的0字符进行倒序)。如果没有删除0字符,那么倒序的文件将会多出一个字符,如果再次调用FileRev函数,将无法使文件还原成它的原始样子。若要删除文件结尾处的0字符,必须后退一步,使用文件管理函数,而不是通过内存映射对文件进行操作。
如果要强制已经倒序的文件在某个位置上结束,就需要将文件指针定位在指定的位置(原始文件的结尾处)并调用SetEndOfFile函数:
// Remove trailing zero character added earlier.
	SetFilePointer(hFile, dwFileSize, NULL, FILE_BEGIN);
	SetEndOfFile(hFile);
注意:SetEndOfFile函数必须在撤消视图的映象并且关闭文件映射对象之后调用,否则,该函数将返回FALSE,GetLastError则返回ERRORUSERMAPPE DFILE。这个
错误表示不能在与文件映射对象相关联的文件上执行文件未尾的操作。

核心代码

BOOL CFileRevDlg::FileReverse()
{
	bool bIsTextUnicode = FALSE;  // Assume text is Unicode
	// Open the file for reading and writing.
	HANDLE hFile = CreateFile(m_DirectoryPath + FILENAME , GENERIC_WRITE | GENERIC_READ ,0,
		NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

	if (hFile == INVALID_HANDLE_VALUE){
		MessageBox(_T("File could not be opened."));
		return FALSE;
	}

	// Get the size of the file (I assume the whole file can be mapped).
	DWORD dwFileSize = GetFileSize(hFile, NULL);

	// Create the file-mapping object. The file-mapping object is 1 character 
	// bigger than the file size so that a zero character can be placed at the 
	// end of the file to terminate the string (file). Because I don't yet know
	// if the file contains ANSI or Unicode characters, I assume worst case
	// and add the size of a WCHAR instead of CHAR.
	HANDLE hFileMap = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 
		0, dwFileSize + sizeof(WCHAR), NULL);

	if (hFileMap == NULL) {
		MessageBox(_T("File map could not be opened."));
		CloseHandle(hFile);
		return FALSE;
	}

	// Get the address where the first byte of the file is mapped into memory.
	PVOID pvFile = MapViewOfFile(hFileMap, FILE_MAP_WRITE, 0, 0, 0);

	if (pvFile == NULL) {
		MessageBox(_T("Could not map view of file."));
		CloseHandle(hFileMap);
		CloseHandle(hFile);
		return FALSE;
	}

	// Does the buffer contain ANSI or Unicode?
	int iUnicodeTestFlags = -1;   // Try all tests
	bIsTextUnicode = IsTextUnicode(pvFile, dwFileSize, &iUnicodeTestFlags);
	SetDlgItemText(IDC_TEXTTYPE,bIsTextUnicode ? TEXT("文件编码:Unicode") : TEXT("文件编码:ANSI"));
	if (!bIsTextUnicode) {
		// For all the file manipulations below, we explicitly use ANSI 
		// functions because we are processing an ANSI file.

		// 文件末尾添加 0,作为字符串的结束符
		PSTR pchANSI = (PSTR) pvFile;
		pchANSI[dwFileSize / sizeof(CHAR)] = 0;

		// Reverse the contents of the file.
		_strrev(pchANSI);

		// Convert all "\n\r" combinations back to "\r\n" to 
		// preserve the normal end-of-line sequence.
		pchANSI = strstr(pchANSI, "\n\r"); // Find first "\r\n".

		while (pchANSI != NULL) {
			// We have found an occurrence....
			*pchANSI++ = '\r';   // Change '\n' to '\r'.
			*pchANSI++ = '\n';   // Change '\r' to '\n'.
			pchANSI = strstr(pchANSI, "\n\r"); // Find the next occurrence.
		}

	} else {
		// For all the file manipulations below, we explicitly use Unicode
		// functions because we are processing a Unicode file.

		// Put a zero character at the very end of the file.
		PWSTR pchUnicode = (PWSTR) pvFile;
		pchUnicode[dwFileSize / sizeof(WCHAR)] = 0;

		if ((iUnicodeTestFlags & IS_TEXT_UNICODE_SIGNATURE) != 0) {
			// If the first character is the Unicode BOM (byte-order-mark),
			// 0xFEFF, keep this character at the beginning of the file.
			pchUnicode++;
		}

		// Reverse the contents of the file.
		_wcsrev(pchUnicode);

		// Convert all "\n\r" combinations back to "\r\n" to 
		// preserve the normal end-of-line sequence.
		pchUnicode = wcsstr(pchUnicode, L"\n\r"); // Find first '\n\r'.

		while (pchUnicode != NULL) {
			// We have found an occurrence....
			*pchUnicode++ = L'\r';   // Change '\n' to '\r'.
			*pchUnicode++ = L'\n';   // Change '\r' to '\n'.
			pchUnicode = wcsstr(pchUnicode, L"\n\r"); // Find the next occurrence.
		}
	}	
	// Clean up everything before exiting.
	UnmapViewOfFile(pvFile);
	CloseHandle(hFileMap);

	// Remove trailing zero character added earlier.
	SetFilePointer(hFile, dwFileSize, NULL, FILE_BEGIN);
	SetEndOfFile(hFile);
	CloseHandle(hFile);	
	return TRUE;
}

效果截图


参考资料

《Windows核心编程》第17章:内存管理

Demo下载

点击下载

版权

原文地址: 曾是土木人

【信息科学与工程学】计算机科学与自动化——第八十四篇 C++分布式软件高并发/高可用算法01 4. 提交:协调者选择提交时间戳(>所有读时间戳),两阶段提交:a) 写意图预提交到所有参与者,b) 参与者持久化后确认,c) 协调者决定提交,异步清理意图。:客户端请求发送到协调节点,协调节点根据路由转发到主分片所在节点。Span有父子关系。1. 索引文档:客户端发送PUT请求到协调节点,协调节点路由到主分片节点,主分片写入本地,然后并行复制到副本分片,等待确认后响应客户端。3. 搜索:客户端发送搜索请求到协调节点,协调节点广播到所有相关分片,每个分片执行查询,返回结果,协调节点合并、排序、分页后返回。 阅读详情

相关推荐

【信息科学与工程学】计算机科学与自动化——第三百零四篇 高性能系统开发指南01

高并发:限流、熔断、降级高性能:红包拆分、多级缓存、大Key/热Key拆分、Pipeline、线程池、RocketMQ零丢失、幂等、分布式锁、集群缩容、分批入库海量数据处理:日志分表分片、跨表查询、冷热分层、大数据引擎服务器选型系统安全:网关安全、服务器安全、云存储安全、风控、监控、测试数据一致性:缓存与数据库一致性、大厂方案、蓝绿回滚、流量一致性、流程一致性项目与团队管理:流程问题、管理问题(风险、成本、人员、文档、培训)稳定性建设:上线三板斧、线上五步闭环、混沌工程、容量规划。

weixin_49199313的博客 249

java倒序输出文件行,文本文件a.txt的内容以倒序的方式输出

package hello;import java.io.*;public class FileReverse {File ifile;FileReverse(String fname)throws IOException {ifile=new File(fname);}public void reverse() {int c;FileInputStream fin;FileOutputStrea...

weixin_36081486的博客 907

油气测井XTF文件解析:从二进制格式到Python数据处理实践

在油气勘探开发领域,测井数据是评估储层的关键。这些数据常以二进制格式存储,以实现高效存储和快速读取。其中,XTF作为一种源自经典5700测井系统及ECLIPS平台的专有二进制格式,承载了大量历史测井数据。理解并解析此类二进制格式,是将数据转化为现代分析工具(如Python、Pandas)可用信息的基础,对于数据迁移、统一数据平台构建及机器学习模型训练至关重要。本文聚焦于**XTF文件**的**二进制结构解析**,深入探讨其自描述性、混合存储的特点,并详细阐述如何通过Python编程,逆向工程其文件头、曲线定

weixin_33462927的博客 342

文件处理篇python

import math r=eval (input ("请输入圆的半径:")) area=math.pi*r*r print("圆面积为:",area)

Ketty_Lin的博客 1883

内存映射的使用——实现大文件内容倒序

将大文件通过文件映射的方式进行逆序!非常好的方法!

逆序输出文本文档txt

将student.txt的内容(每一行的内容为:学号+空白+姓名)倒着输出成outStudent.txt(最后一行变到第一行),并且学号跟名字中间加上|号,详情参照所给的student.txt以及outStudent.txt

文件按行逆序的简单实现

前两天被同学问到一个简单的问题,将一个文本文件中的内容按行倒转过来,每行的内容不变。自己试了好一会,才发现C的FILE的那些操作都忘得差不多了。。。 一开始是准备创建一个新文件,读一行就往新文件里写一行,再把流位置重置为文件头,后来发现FILE的文件流不是insert的,而是直接覆盖。。失败了 只好先把文件内容先全部放在内存里,再rewind到文件流的头,倒序把内容写到文件中去。 #incl

zhangdaodan的专栏 1836

VC利用内存映射实现进程间通信

在Windows上,系统保证在同一文件映射对象的多个视图间保持一致。这是同一台机器上共享数据的最底层机制,也可以作为进程通讯的基础。

按行顺序存放c语言,C语言实现文件按行倒序存储

从A文件读取文本存储到B文件里,但是B文件里的文本顺序要和A文件里的顺序相反,比如A文件里的文本是:sunmoon那么B文件里的内容就必须是:moonsun采用了双向链表实现这一功能,C语言的实现代码如下:#include #include int main(){FILE *file_in,*file_out;struct st{char c[1024];//存储读、写的数据,因此文件每行的数据不...

weixin_28802509的博客 632

文件映射实现文件逆序

采用文件映射(CreateFileMapping与MapViewOfFile)可快速实现大文件(>4G)的逆序输出,并且能快速根据行号索引行号内容!

使用内存映射修改大文件

本文介绍利用内存映射文件修改大文件:在大文件内存前加入一段数据,若要使用内存映射文件,必须执行下列操作步骤: 1.创建或打开一个文件内核对象,该对象用于标识磁盘上你想用作内存映射文件的文件; 2.创建一个文件映射内核对象,告诉系统该文件的大小和你打算如何访问该文件; 3.让系统将文件映射对象的全部或一部分映射到你的进程地址空间中;

C++倒序按行读取文件

前言: 因为有些文件是以追加方式进行写入的,最新数据在最后一行,所以在展示数据时阅读习惯是从最新的开始看,所以诞生了倒序按行读取文件的需求。 如文件: 第一行 第二行 第三行 期望读取效果: 第三行 第二行 第一行 源码使用的C++11: #include <iostream> #include <fstream> #include <string.h> #include <vector> using namespace...

CrazyAhai的专栏 2416

别再硬拔了!用这3个终端命令轻松搞定Mac上移动硬盘‘被程序占用’的问题

本文介绍了3个终端命令解决Mac上移动硬盘‘被程序占用’的问题,包括使用`diskutil list`定位硬盘、`lsof`查找占用进程以及`diskutil unmount`安全卸载。这些方法能有效避免数据风险,提升操作效率,特别适合开发者和技术爱好者。

weixin_33507732的博客 294

Windows API一日一练(56)SetEndOfFile和GetFileSizeEx函数

有一天,我正在开发BT软件,它有这样的一个功能,就是先把文件的大小分配好,然后再慢慢地往里面对应的位置写入相应的数据。这样的好处,就是可以先把磁盘空间占用起来,以便后面的下载顺利进行。要实现这个功能,就需要创建一个空的文件,然后把文件指针设置到相应大小的位置,然后再调用函数SetEndOfFile来设置文件的结束位置,这样文件就有相应的大小了。在BT软件的开发里,也发现目录的处理时需要详...

anjichan4261的博客 354

【Flink】状态编程: 订单超时告警

文章目录一、基础概念二、Flink状态编程1、支持的状态类型2、Managed Keyed State六种类型基本API状态的生命周期3、Managed Operator State三、案例:订单延迟告警统计1、需求描述2、需求分析3、数据与模型4、详细实现 一、基础概念 在Flink架构体系中,有状态计算可以说是Flink非常重要的特性之一。 有状态计算是指: 在程序计算过程中,在Flink...

一只皮皮熊 2862

ABAP BAPI_PRODORD_CHANGE函数详解:如何高效重读生产订单主数据

本文深入解析ABAP BAPI_PRODORD_CHANGE函数在生产订单主数据高效处理中的应用。通过详细讲解函数架构、主数据重读机制及实战代码示例,帮助开发人员掌握生产订单数据的精准读取与更新技术,提升SAP系统集成与自动化处理效率。

weixin_29207149的博客 468

一种不需要内存申请指针反序,一种内存申请指针反序

#include <stdio.h> #include <stdlib.h> #include <string.h>int main(){ /* char* src = "hello,world"; int len = strlen(src); char* dest = (char*)malloc(len+1);//要为\0分配一个空间 char* d =

qwe13600as的博客 298

Kali Linux实战:Aircrack-ng破解Wi-Fi密码的完整流程与常见问题解决

本文详细介绍了在Kali Linux中使用Aircrack-ng套件进行Wi-Fi密码破解的完整流程,包括环境准备、无线网卡配置、网络扫描、握手包捕获与字典破解等关键步骤。同时针对无线网卡不支持监听模式、无法捕获握手包等常见问题提供了实用解决方案,帮助安全研究人员有效评估无线网络安全性。

weixin_29323049的博客 297

一个小菜鸟对数据在内存中的二进制存储的理解

之前一直不理解数据在内存中的存储方式,只知道教科书上写死的是整数在内存中以补码形式储存,所谓的补码就是根据整数的原码,正数的补码就是原码本身,负数则是原码除符号位外每一位都取反然后加一,例如整数10 以8位二进制表示时的原码为00001010,则按照补码的转换规则,其补码为00001010,-10的补码为11110110。 但是只有这么一种感性的认识,并没有亲身实验过,今天突然心血来潮就写了个小

baidu_20792589的博客 4408

carsim软件教学

第一步打开小锁(红色标注) 新手往往一看界面是灰的,界面内的各种模块打开不了,以为没激活成功 所有模块必须复制之后,进行编辑,不要直接进行修改(很重要) 2.空气动力学模型(红色标注) 这里面主要设定了簧上质量。整车的整备质量在下图模块中进行设定 空气动力学。主要涉及到空气阻力,在下面模块中进行设定,有个问题需要注意,他的空气阻力与汽车理论的空气阻力公式不一致,这一点需要注意 下面这会模块基本上用不到,涉及到一个声音和汽车的外观 下面这个模块主要涉及到发动机功率,传动比还有 tao,档位的传动比,发

weixin_43796045的博客 2551

Linux加密框架中的算法和算法模式(1)——算法介绍

算法和算法模式

yangguoyu8023的博客 2032
上一篇: 虚拟地址空间
下一篇: libcurl之curl_easy_getinfo的使用教程
曾是土木人
博客等级 码龄15年 67粉丝 29原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值