VC6++内存映射修改大文件方法

合集下载

vc6.0配置及使用教程

vc6.0配置及使用教程

步骤是:(先工程—后文件—编译—连接---运行)1,建立一个工程,“文件”——“新建”,出现下面界面:选择“Win32 Console Application”(控制台应用程序,左边倒数第三个),命名工程名称,选择保存位置,点击“确定”,进入下一步,看到如下提示界面:建立一个空工程,对应其他需要的你一可以建立别的工程;点击“完成”,之后:显示你创建的工程的信息。

2,再在有一个的工程的条件下,我们再建立一个源文件;“文件”——“新建”(快捷键Ctri+N),出现:建立源文件,选择“C++ Source ”,一般都是建立这种文件的(适用在当文件中适用)如果要建立头文件的话,选择“C/C++ Header File”,(适用在多文件工程中使用)命名,文件名称,点击“确定”,之后:进入编辑区,在主界面编写代码:如下编写完之后呢:可以按编译按钮调试程序,看看有没有错误,有的话改正,没有的话就可以再按连接按钮检查连接(多文件工程时常用,检查文件间是否正常连接),最后,点运行按钮,就可以运行了。

如果是您有代码如:cpp文件,或 .h 文件,想添加都VC6.0里来测试的话,可以这样做:首先,要理解一下文件扩展名为:cpp和.h文件扩张名是.h,代表的是头文件,一般是书写一些函数原型,以及一些在整个程序中常用到的结构体,频繁使用的函数说明,定义等等;文件扩张名为,cpp的,是C++中的源文件,也是最常用到的文件,每建立一个工程都要至少一个源文件(至少要有一个函数入口——主函数main() ),包含了核心代码;建立与运行说明:(以VC 6.0编译器为例,其他编译器类似)首先,打开VC 6.0编译环境;在菜单栏——文件(的下拉菜单中选择“新建”),在弹出的选择窗口中,选择Win32 Console Application(控制台应用程序),在填写工程名称,选择一个程序保存路径,点击“完成”,查看工程信息。

在点击“确定”,就建立一个简单的工程了。

vc6的使用流程

vc6的使用流程

VC6的使用流程1. 准备工作在开始使用VC6进行开发之前,需要准备以下工作:•安装VC6软件,确保已经正确安装。

•确保已经安装了适当的编译器和调试器。

•确保已经安装了所需的库文件和依赖项。

2. 创建项目VC6中创建项目的方法如下:1.打开VC6软件。

2.在菜单栏中选择“文件” -> “新建” -> “项目”。

3.在弹出的对话框中选择“Win32应用程序”或其他合适的模板。

4.输入项目的名称和保存路径。

5.点击“确定”按钮创建项目。

3. 设置项目属性在创建项目后,需要设置项目的属性以满足开发需求。

以下是设置项目属性的一般步骤:1.在VC6的“项目视图”中,选择项目文件。

2.在菜单栏中选择“项目” -> “设置”。

3.在弹出的对话框中,选择需要设置的属性,如“C/C++”、“链接器”等。

4.根据需求进行属性设置,例如指定包含目录、库文件路径等。

5.点击“确定”按钮保存设置。

4. 编写代码在VC6中,可以使用C或C++语言编写代码。

以下是编写代码的一般步骤:1.在“资源视图”中,选择需要编辑的源文件。

2.在代码编辑器中编写代码。

3.可以使用VC6提供的自动完成、语法高亮等功能来提升编码效率。

4.完成代码编写后,保存文件。

5. 编译和调试在代码编写完成后,可以进行编译和调试。

以下是编译和调试的一般步骤:1.在菜单栏中选择“生成” -> “全部重新生成”或“生成” -> “生成解决方案”。

2.编译器将会编译代码,并生成可执行文件。

3.在VC6中可以进行单步调试、断点设置等操作,以便于调试代码。

4.调试完成后,可以查看调试结果并进行必要的修正。

6. 运行和发布在完成编译和调试后,可以运行和发布项目。

以下是运行和发布的一般步骤:1.点击菜单栏中的“调试” -> “开始执行”或使用快捷键F5,运行程序。

2.程序将会在VC6中启动,并在控制台或窗口中显示运行结果。

3.如果需要发布项目,可以通过“生成”菜单中的“发布…”选项来进行发布设置。

vc6调试技巧

vc6调试技巧

vc6调试技巧难怪很多前辈说调试是⼀个程序员最基本的技能,其重要性甚⾄超过学习⼀门语⾔。

不会调试的程序员就意味着他即使会⼀门语⾔,却不能编制出任何好的软件。

我以前接触的程序⼤多是有⽐较成形的思路和⽅法,调试起来出的问题都⽐较⼩,最近这个是我⾃⼰慢慢摸索调试,接触了很多新的调试⽅法,并查了很多前辈的总结,受益匪浅,总结以前的和新的收获如下:VC调试篇设置为了调试⼀个程序,⾸先必须使程序中包含调试信息。

⼀般情况下,⼀个从AppWizard创建的⼯程中包含的Debug Configuration⾃动包含调试信息,但是是不是Debug版本并不是程序包含调试信息的决定因素,程序设计者可以在任意的Configuration中增加调试信息,包括Release版本。

为了增加调试信息,可以按照下述步骤进⾏:打开Project settings对话框(可以通过快捷键ALT+F7打开,也可以通过IDE菜单Project/Settings打开)选择C/C++页,Category中选择general ,则出现⼀个Debug Info下拉列表框,可供选择的调试信息⽅式包括:选择Link页,选中复选框"Generate Debug Info",这个选项将使连接器把调试信息写进可执⾏⽂件和DLL如果C/C++页中设置了Program Database以上的选项,则Link incrementally可以选择。

选中这个选项,将使程序可以在上⼀次编译的基础上被编译(即增量编译),⽽不必每次都从头开始编译。

调试⽅法:1、使⽤ Assert(原则:尽量简单)assert只在debug下⽣效,release下不会被编译。

2、防御性的编程3、使⽤Trace4、⽤GetLastError来检测返回值,通过得到错误代码来分析错误原因5、把错误信息记录到⽂件中位置断点(Location Breakpoint)⼤家最常⽤的断点是普通的位置断点,在源程序的某⼀⾏按F9就设置了⼀个位置断点。

vc 6.0的使用技巧

vc 6.0的使用技巧

介绍VC6.0的18个实用小技巧VC 用的太熟的一个后果是看到有人用UltraEdit写VC程序时觉得不可理解。

另一个后遗症是,我很喜欢用快捷键,熟悉了VC的这套快捷键后,用其他软件的时候,如果快捷键设置和VC的习惯设置冲突就觉得很难受。

比如说SoftIce,很久以前就开始用,至今还没习惯。

下面说说我在使用VC IDE时经常用到的一些快捷键。

CTRL+TAB:在IDE打开的文件间切换。

我喜欢在IDE里同时打开很多文件,用CTRL+TAB来回切换,浏览代码很方便。

LEO的习惯跟我相反,他看完一个文件后会顺手把文件关掉。

有一次他看到我的IDE里居然开了几十个文件,惊讶坏了,呵呵。

CTRL+SHIFT+SPACE:快速查看函数声明。

有了这个以后查MSDN的次数大大减少。

CTRL+]:快速定位{}。

看代码时常用,另外用来检查大括号是否配对很方便。

相比之下page up/page down用的比较少,因为老是觉得这个定位代码不够精确。

CTRL+SHFT+]:选中大括号之间的代码。

代码段拷贝的时候常用。

在一次移植一段C 程序到C++程序时学会的。

F12:快速定位到宏/变量/函数的定义。

VC6第一次用要先生成BROWSE INFO,速度比较慢,VS2003可以直接定位。

ALT+F8:格式化代码。

常和CTRL+A或者CTRL+SHIFT+]连用。

我看到格式不整齐的代码时会很难受。

CTRL+X, CTRL+C, CTRL+V:有时候跟别人开玩笑说,其实编程挺简单的,会CTRL+C/CTRL+V就行。

CTRL+Z, CTRL+Y:UNDO, REDO。

修改代码时常用。

CTRL+F2, F2:设置、查看书签。

在VS2003中一度习惯了CTRL+K, K/CTRL+K/N, CTRL+K/P的组合,后来由于来回在VC6、VS2003之间切换,还是觉得统一用CTRL+F2, F2比较好。

ALT+-->, ALT+<--:光标移到下个单词。

VC6.0在32位机中对大数据量文件操作的扩展

VC6.0在32位机中对大数据量文件操作的扩展

VC6.0在32位机中对大数据量文件操作的扩展摘要:目前,随着计算机在各个产业部门的逐渐普及、计算机运算能力的逐步提高以及各种新型需求的诞生,对文件存储以及访问的需求也随之升高,人们已经不能满足于基于兆级的数据文件的访问,更大的数据文件的访问和支持能力对开发人员提出了更高的要求,但是,受计算机硬件条件、系统软件的版本以及软件开发版本的约束,我们并不能大刀阔斧的对软件进行彻底修改,否则会对软件的兼容性造成非常严重的危害,因此我们需要针对不同情况来分别对各种大型数据进行遍历,从而保证软件在不同配置的计算机上能够顺利运行。

关键词:新型需求彻底修改遍历引言:在石油及矿产勘探领域,经常使用不同方式对地层进行探测,随着探测手段日益增强,衍生出的数据量也越来越大,从早期的几十兆到现在的几个G的级别,不仅对计算机的要求日益提高,同时对软件开发人员也提出了更高的要求:开发人员要花费大量精力来优化内存以及CPU的使用,并且还要针对一些数据结构不能操作大型数据进行扩展。

本文针对某油田测井数据格式的大数据量文件的操作,分别阐述了几种不同情况的处理方法。

本程序是基于VC6.0开发的,其运行环境为32位Windows系统。

1 修改数据描述格式:首先,我们需要面对的是数据格式不能满足需求的问题,对所有标识文件数据块大小的字段进行类型的修改,原有的代码中没有考虑到大数据量的可能性,对数据块大小的描述都是采用的整型int型或长整型long格式,由于采用的是有符号整型,所以其只能标识-2147483648~2147483648的文件块大小,这对于一般的线性数据块大小是足够的,但是对于大范围的波列数据以及矩阵类型数据的描述就捉襟见肘了。

本程序采用了一种叫做ULONGLONG的据格式,该格式为无符号64位数据格式,理论上可以达到0~18446744073709551616的存储长度,这样的话对于任意可能存在的数据长度,该格式都是足够描述的。

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

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

VC中用内存映射文件处理大文件摘要:本文通过内存映射文件的使用来对大尺寸文件进行访问操作,同时也对内存映射文件的相关概念和一般编程过程作了较为详细的介绍。

关键词:内存映射文件;大文件处理;分配粒度引言文件操作是应用程序最为基本的功能之一,Win32 API和MFC均提供有支持文件处理的函数和类,常用的有Win32 API的CreateFile()、WriteFile()、ReadFile()和MFC提供的CFile类等。

一般来说,以上这些函数可以满足大多数场合的要求,但是对于某些特殊应用领域所需要的动辄几十GB、几百GB、乃至几TB的海量存储,再以通常的文件处理方法进行处理显然是行不通的。

目前,对于上述这种大文件的操作一般是以内存映射文件的方式来加以处理的,本文下面将针对这种Windows核心编程技术展开讨论。

内存映射文件概述内存文件映射也是Windows的一种内存管理方法,提供了一个统一的内存管理特征,使应用程序可以通过内存指针对磁盘上的文件进行访问,其过程就如同对加载了文件的内存的访问。

通过文件映射这种使磁盘文件的全部或部分内容与进程虚拟地址空间的某个区域建立映射关联的能力,可以直接对被映射的文件进行访问,而不必执行文件I/O操作也无需对文件内容进行缓冲处理。

内存文件映射的这种特性是非常适合于用来管理大尺寸文件的。

在使用内存映射文件进行I/O处理时,系统对数据的传输按页面来进行。

至于内部的所有内存页面则是由虚拟内存管理器来负责管理,由其来决定内存页面何时被分页到磁盘,哪些页面应该被释放以便为其它进程提供空闲空间,以及每个进程可以拥有超出实际分配物理内存之外的多少个页面空间等等。

由于虚拟内存管理器是以一种统一的方式来处理所有磁盘I/O的(以页面为单位对内存数据进行读写),因此这种优化使其有能力以足够快的速度来处理内存操作。

使用内存映射文件时所进行的任何实际I/O交互都是在内存中进行并以标准的内存地址形式来访问。

VC++ 6.0使用教程

VC++ 6.0使用教程

VC++ 6.0 使用教程------李发军一、启动VC++6.01)点击桌面快捷方式,或者从所有程序中找到Microsoft Visual C++ 6.0启动。

2)进入后出现如下界面:直接将每日提示关闭即可。

二、单个文件的编辑、编译、运行1)点击左上角文件——新建2)弹出新建文件对话框,切换到文件栏,选择C++ Source File,输入文件名,也可自己选择文件存储的位置,如下:3)完成之后点确定,到编辑界面,编辑好我们需要的程序,如下:4)接下来请看屏幕右上方,,点(快捷键Ctrl+F7)编译,点(快捷键F7)连接,编译结果请看左下角,如下:如果出现该提示,说明程序没有问题,点(快捷键Ctrl+F5)即可运行程序,如果没有出现类似的提示,那你得好好想想了!!!好了,单个文件的是比较简单的,下面请看多个文件的!三、工程(多个)文件的编辑、编译、调试1)首先,还是点左上角文件——新建,出现新建文件对话框,如下:2)由于源文件有多个文件<.cpp>(也可能有头文件<.h>),所以我们选择新建工程,因此切换到工程栏目,选择win 32 Console Application,输入工程名,选择好存储的位置,如下:3)完成之后点确定,到如下界面,选择新建一个空工程:4)点击完成,然后确定,到了如下界面:5)现在点击左下角工程信息中的FileView选项,可以看到刚才新建的工程,再点击工程前面的+号,可以看到三个文件夹,分别对应于源文件,头文件和资源文件,如下:6)现在可以在工程里面添加需要的文件了,添加新建文件(.h文件和.cpp文件)的方法已经介绍过了,点击文件——新建,出现新建文件对话框,切换到文件栏目,选择C++ Source Code,输入文件名等等,如下:7)如果要添加已经存在的文件,那么就右键单击Source Files或者Header Files文件夹,选择添加文件到目录,出现添加文件对话框,现在就可以添加自己想要的文件到工程中了,如下:四、VC++ 6.0中的调试VC++6.0中的调试比较简单,主要是几个快捷键的应用。

通过VC++内存映射修改大文件方法

通过VC++内存映射修改大文件方法

通过VC++内存映射修改大文件方法本文介绍利用VC++内存映射文件修改大文件的方法:在大文件内存前加入一段数据,若要使用内存映射文件,必须执行下列操作步骤:1.创建或打开一个文件内核对象,该对象用于标识磁盘上你想用作内存映射文件的文件;2.创建一个文件映射内核对象,告诉系统该文件的大小和你打算如何访问该文件;3.让系统将文件映射对象的全部或一部分映射到你的进程地址空间中;当完成对内存映射文件的使用时,必须执行下面这些步骤将它清除:1.告诉系统从你的进程的地址空间中撤消文件映射内核对象的映像;2.关闭文件映射内核对象;3.关闭文件内核对象;下面将用一个实例详细介绍这些操作步骤,(本实例的目的就是将一个文件A其内容前面加入一些内容存入文件B,我想大家在程序开发当中会遇到这种情况的)。

一、我们打开关于A文件内核对象,并创建一个关于B文件的内核对象若要创建或打开一个文件内核对象,总是要调用CreateFile函数:HANDLE CreateFile(PCSTR pszFileName,DWORD dwDesiredAccess,DWORD dwShareMode,PSECURITY_ATTRIBUTES psa,DWORD dwCreationDisposition,DWORD dwFlagsAndAttributes,HANDLE hTemplateFile);CreateFile函数拥有好几个参数,这里只重点介绍前3个参数,即szFileName,dwDesiredAccess 和dwShareMode。

你可能会猜到,第一个参数pszFileName用于指明要创建或打开的文件的名字(包括一个选项路径),第二个参数dwDesiredAccess用于设定如何访问该文件的内容,可以设定下表所列的4个值中的一个。

当创建或打开一个文件,将它作为一个内存映射文件来使用时,请选定最有意义的一个或多个访问标志,以说明你打算如何访问文件的数据,对内存映射文件来说,必须打开用于只读访问或读写访问的文件,因此,可以分别设定GENERIC_READ或GENERIC_READ|GENERIC_WRITE, 第三个参数dwShareMode 告诉系统你想如何共享该文件,可以为dwShareMode设定下表所列的4个值之一:如果CreateFile函数成功地创建或打开指定的文件,便返回一个文件内核对象的句柄,否则返回INVALID_HANDLE_VALUE, 注意能够返回句柄的大多数Windows函数如果运行失败,那么就会返回NULL,但是,CreateFile函数将返回INVALID_HANDLE_VALUE,它定义为((HANDLE)-1),HANDLEhFile=CreateFile(".\\first.txt",GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTI NG,FILE_FLAG_SEQUENTIAL_SCAN,NULL);HANDLEhmyfile=CreateFile("E:\\my.txt",GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL );二、我们要分别创建两个文件映射内核对象调用CreateFile函数,就可以将文件映像的物理存储器的位置告诉操作系统,你传递的路径名用于指明支持文件映像的物理存储器在磁盘(或网络或光盘)上的确切位置,这时,必须告诉系统,文件映射对象需要多少物理存储器,若要进行这项操作,可以调用CreateFileMapping函数:HANDLE CreateFileMapping(HANDLE hFile,PSECURITY_ATTRIBUTES psa,DWORD fdwProtect,DWORD dwMaximumSizeHigh,DWORD dwMaximumSizeLow,PCTSTR pszName);第一个参数hFile用于标识你想要映射到进程地址空间中的文件句柄,该句柄由前面调用的CreateFile函数返回,psa参数是指向文件映射内核对象的SECURITY_ATTRIBUTES结构的指针,通常传递的值是NULL(它提供默认的安全特性,返回的句柄是不能继承的)。

终于搞定了微软那个64K的内存映射文件的分配粒度偏移量

终于搞定了微软那个64K的内存映射文件的分配粒度偏移量

终于搞定了微软那个64K的内存映射文件的分配粒度偏移量终于搞定了微软那个64K的内存映射文件的分配粒度偏移量2007-12-20 11:19这个狗屁64K让我郁闷了实在太久,也是我的错,其实实现了以后再看非常简单的东西,我算法的基本功太差。

mark it!移动内存/*to_offset|\/|---len--|from_offset-&gt;| | | ||-----------|---|----|---|| | | | || | | | || | | | ||-----------|---|----|---||---len--|*/ DWORD dwBytesInBlock = GetAllocationGranularity(); // 要拷贝的长度int64 qwCopySize = len; int64 qwStartOffset1, qwStartOffset2;int64 nBlocks1, nBlocks2;DWORD nResidue1, nResidue2;int64 qwOffset1, qwOffset2;DWORD dwCopyBlock = dwBytesInBlock; char* tmp = (char*)MALLOC(dwBytesInBlock, false, GC_ATOMIC);assert(tmp != 0); // 后一个条件是拷贝长度小于一个粒度的时候,也是正着拷if (to_offset &gt; from_offset &amp;&amp; len &gt; dwBytesInBlock){// 靠前的内存拷到后面去// 反着拷qwStartOffset1 = from_offset + len - dwCopyBlock;qwStartOffset2 = to_offset + len - dwCopyBlock; while (qwCopySize &gt; 0){if (qwStartOffset1 &lt; from_offset)qwStartOffset1 = from_offset;if (qwStartOffset2 &lt; to_offset)qwStartOffset2 = to_offset; // srcnBlocks1 = qwStartOffset1 / dwBytesInBlock;nResidue1 = (DWORD)(qwStartOffset1 % dwBytesInBlock);qwOffset1 = nBlocks1 * dwBytesInBlock;// dstnBlocks2 = qwStartOffset2 / dwBytesInBlock;nResidue2 = (DWORD)(qwStartOffset2 % dwBytesInBlock);qwOffset2 = nBlocks2 * dwBytesInBlock;if (qwCopySize &lt; dwBytesInBlock)dwCopyBlock = (DWORD)qwCopySize; LPBYTE pAddress1 = (LPBYTE)MapViewOfFile(mapping, FILE_MAP_ALL_ACCESS, (DWORD)(qwOffset1 &gt;&gt;32), (DWORD)(qwOffset1 &amp; 0xFFFFFFFF), dwCopyBlock + nResidue1);assert(pAddress1 != 0);memcpy(tmp, pAddress1 + nResidue1, dwCopyBlock);// 为了性能,不用调试了就不多这步了//#ifdef _DEBUG// memset(pAddress1 + nResidue1, 0, dwCopyBlock);//#endif // _DEBUGUnmapViewOfFile(pAddress1);LPBYTE pAddress2 = (LPBYTE)MapViewOfFile(mapping, FILE_MAP_ALL_ACCESS, (DWORD)(qwOffset2 &gt;&gt;32), (DWORD)(qwOffset2 &amp; 0xFFFFFFFF), dwCopyBlock + nResidue2);assert(pAddress2 != 0);memcpy(pAddress2 + nResidue2, tmp, dwCopyBlock);UnmapViewOfFile(pAddress2); qwStartOffset1 -= dwCopyBlock;qwStartOffset2 -= dwCopyBlock;qwCopySize -= dwCopyBlock;}}else // from_offset &gt; to_offset{// 靠后的内存拷到前面去// 正着拷qwStartOffset1 = from_offset;qwStartOffset2 = to_offset; while (qwCopySize &gt; 0){// srcnBlocks1 = qwStartOffset1 / dwBytesInBlock;nResidue1 = (DWORD)(qwStartOffset1 % dwBytesInBlock);qwOffset1 = nBlocks1 * dwBytesInBlock;// dstnBlocks2 = qwStartOffset2 / dwBytesInBlock;nResidue2 = (DWORD)(qwStartOffset2 % dwBytesInBlock);qwOffset2 = nBlocks2 * dwBytesInBlock;if (qwCopySize &lt; dwBytesInBlock)dwCopyBlock = (DWORD)qwCopySize; LPBYTE pAddress1 = (LPBYTE)MapViewOfFile(mapping, FILE_MAP_ALL_ACCESS, (DWORD)(qwOffset1 &gt;&gt;32), (DWORD)(qwOffset1 &amp; 0xFFFFFFFF), dwCopyBlock + nResidue1);assert(pAddress1 != 0);memcpy(tmp, pAddress1 + nResidue1, dwCopyBlock);// 为了性能,不用调试了就不多这步了//#ifdef _DEBUG// memset(pAddress1 + nResidue1, 0, dwCopyBlock);//#endif // _DEBUGUnmapViewOfFile(pAddress1);LPBYTE pAddress2 = (LPBYTE)MapViewOfFile(mapping, FILE_MAP_ALL_ACCESS, (DWORD)(qwOffset2 &gt;&gt;32), (DWORD)(qwOffset2 &amp; 0xFFFFFFFF), dwCopyBlock + nResidue2);assert(pAddress2 != 0);memcpy(pAddress2 + nResidue2, tmp, dwCopyBlock);UnmapViewOfFile(pAddress2); qwStartOffset1 += dwCopyBlock;qwStartOffset2 += dwCopyBlock;qwCopySize -= dwCopyBlock;}} FREE(tmp);读// 粒度DWORD dwBytesInBlock = GetAllocationGranularity(); int64 qwCopySize = len; int64 qwStartOffset = offset;int64 nBlocks;DWORD nResidue;int64 qwOffset;DWORD dwCopyBlock = dwBytesInBlock; while (qwCopySize &gt; 0){nBlocks = qwStartOffset / dwBytesInBlock;nResidue = (DWORD)(qwStartOffset % dwBytesInBlock);qwOffset = nBlocks * dwBytesInBlock; if (qwCopySize &lt; dwBytesInBlock)dwCopyBlock = (DWORD)qwCopySize; LPBYTE pAddress = (LPBYTE)MapViewOfFile(mapping, FILE_MAP_READ, (DWORD)(qwOffset &gt;&gt; 32), (DWORD)(qwOffset &amp; 0xFFFFFFFF), dwCopyBlock + nResidue);assert(pAddress != 0); memcpy((char*)dst + (len - qwCopySize), pAddress + nResidue, dwCopyBlock); UnmapViewOfFile(pAddress); qwStartOffset += dwCopyBlock;qwCopySize -= dwCopyBlock;}写DWORD dwBytesInBlock = GetAllocationGranularity(); // 要拷贝的长度int64 qwCopySize = len; int64 qwStartOffset = offset;int64 nBlocks;DWORD nResidue;int64 qwOffset;DWORD dwCopyBlock = dwBytesInBlock; while (qwCopySize &gt; 0){nBlocks = qwStartOffset / dwBytesInBlock;nResidue = (DWORD)(qwStartOffset % dwBytesInBlock);qwOffset = nBlocks * dwBytesInBlock; if (qwCopySize &lt; dwBytesInBlock)dwCopyBlock = (DWORD)qwCopySize; LPBYTE pAddress = (LPBYTE)MapViewOfFile(mapping, FILE_MAP_ALL_ACCESS, (DWORD)(qwOffset &gt;&gt; 32), (DWORD)(qwOffset &amp; 0xFFFFFFFF), dwCopyBlock + nResidue);assert(pAddress != 0); memcpy(pAddress + nResidue, (char*)src + (len - qwCopySize), dwCopyBlock); UnmapViewOfFile(pAddress); qwStartOffset += dwCopyBlock;qwCopySize -= dwCopyBlock;}粒度是至少是SYSTEM_INFO.dwAllocationGranularity,也可以是N倍,我试了试64K粒度和64M粒度拷贝,后者效率明显要高使用了long long或者说__int64的数据格式,操作的文件可以大至16EB。

vc6.0安装教程与调试技巧

vc6.0安装教程与调试技巧

vc6.0安装教程与调试技巧vc6.0的安装过程1.首先解压安装文件的压缩包2.然后再选择安装的版本,VC6CN 表示的是中文版,VC6EN表示英文版。

3.打开VC6CN文件夹,其中有如下图标,鼠标双击。

4.如下图所示就是我们安装的第一步,单击下一步。

5.选择“接受协议”后单击下一步。

6.本软件属于破解版,故无需输入产品ID号码,直接单击下一步。

7.选择“安装visual c++6.0中文企业版(I)”,这就是我们要安装的程序,单击下一步。

8.单击下一步。

9.如下界面,单击“继续”,开始安装软件。

10.点击“确定”。

11.选择“是”,继续安装。

12.选择“typical”继续安装13.选择“ok”。

14.选择“确定”15.选择“确定”16.取消“安装MSDN”前面的勾号,选择“退出”。

17.选择“是”,取消MSDN的安装。

18.程序安装完毕,再电脑的“开始菜单”中,选择“所有程序”,在“Microsoft Visual C++ 6.0”目录中选择“Microsoft Visual C++6.0”就可以运行程序了。

也可以将这个图标发送到桌面快捷方式,这样就可以直接在桌面上运行程序。

调试技巧调试程序可以帮助的了解程序是怎样运行的。

1、如何快速地规范代码缩进格式选中所需要规范的代码,按shift+F82、如何在Release状态下进行调试Project->Setting…->Project Settings对话框,选择Release 状态。

“C/C++”标签页中的Category选General,Optimizations 选Disable(Debug),Debug info选Program Database。

在“Link”标签页中选中Generate debug info复选框。

注:只是一个介乎Debug和Release的中间状态,所有的ASSERT、VERIFY都不起作用,函数调用方式已经是真正的调用,而不查表,但是这种状态下QuickWatch、调用队列跟踪功能仍然有效,和Debug版一样。

使用内存映射文件处理大文件应用示例

使用内存映射文件处理大文件应用示例

使用内存映射文件处理大文件应用示例在许多应用程序中,处理大文件可能是一项具有挑战性的任务。

传统的文件操作方式会占用大量的内存,并且读取和写入过程也可能非常缓慢。

为了解决这个问题,许多开发人员开始使用内存映射文件来处理大文件。

本文将通过一个示例来介绍如何使用内存映射文件处理大文件。

首先,我们需要了解内存映射文件是什么。

内存映射文件是一种将磁盘文件映射到内存中的机制。

通过将文件的内容映射到内存中,我们可以直接在内存中进行读写操作,而无需将整个文件加载到内存中。

这种方式不仅可以减少内存的使用量,还可以提高读写的效率。

下面我们通过一个具体的示例来说明如何使用内存映射文件处理大文件。

假设我们有一个大小为2GB的日志文件,我们需要对其中的一些数据进行分析。

首先,我们需要创建一个内存映射文件。

```pythonimport mmap# 打开文件file = open('log.txt', 'r+b')# 将文件映射到内存中mm = mmap.mmap(file.fileno(), 0)# 关闭文件file.close()```现在,我们可以通过`mm`对象访问文件的内容。

接下来,我们可以使用正则表达式来查找文件中的特定数据。

```pythonimport re# 在内存映射文件中查找匹配的字符串result = re.findall(b'pattern', mm)# 打印匹配结果print(result)```在这个示例中,我们使用了正则表达式`pattern`来查找文件中匹配的字符串。

`findall()`方法返回的是一个列表,包含了所有找到的匹配结果。

现在,我们可以对匹配结果进行进一步的处理,例如统计匹配结果的数量。

```python# 计算匹配结果的数量count = len(result)# 打印匹配结果的数量print(count)```使用内存映射文件处理大文件不仅可以提高读取文件的效率,还可以减少内存的使用量。

VC6.0使用教程4.0汇总

VC6.0使用教程4.0汇总
栏上依次点击“Compile ..”“Build ..”“Excute ..”来对程序进行编译、连接和运行,并观察程序运 行结果。
24
方法/步骤
25
方法/步骤
26
方法/步骤
程序的错误修改 如果编译或者连接过程中出现错误,底部信息提示
窗口会提示错误所在行以及错误的类型,双击即可定 位到相应的代码处进行修改,尔后重新编译连接运行 ,重复此过程直到程序功能达到要求没有错误。
4
基本概念
代码文件: 用于存储程序的文件,C++ 代码文件的扩展名为
.cpp ,C 语言代码文件的扩展名为 .c ,存储函数或 者变量声明的头文件扩展名一般为 .h 。
5
基本概念
调试(DEBUG): 输入代码、编译、连接、运行并不断修正错误的整
个过程。
6
基本概念
发布(RELEASE): 指程序完成代码的编写和功能调试,最终编译和分
36
注意事项
2)main already defined in ???.obj 一个项目对应一个可执行文件,终端程序中只能有
一个 main 函数,如果你添加了两个都带有 main 函 数的 cpp 文件到同一个项目,则会出现此错误。
解决办法:在 FileView 视图下找到 source file 下的 cpp 文件按 del 将其从项目中剔除,或者临时 注释掉其中一个 cpp 中的代码。
37
注意事项
3)unknown character 0xa3 cpp 代码中除注释和常量外只能出现半角字符,所
以如果代码是从其他地方粘贴过来的,则常常会出现 此类错误,并且很多非法字符是不可见的。
解决办法:尽量手工录入代码,或者将空白部分都 删掉然后重新格式化代码。

VC++6.0使用方法

VC++6.0使用方法

Visual C++ 6.0上机指南一、Visual C++ 6.0概述Visual C++6.0是微软公司推出的目前使用极为广泛的基于Windows平台的可视化集成开发环境,它和Visual Basic、Visual Foxpro、Visual J++等其它软件构成了Visual Studio(又名Developer Studio)程序设计软件包。

Developer Studio是一个通用的应用程序集成开发环境,包含了一个文本编辑器、资源编辑器、工程编译工具、一个增量连接器、源代码浏览器、集成调试工具,以及一套联机文档。

使用Visual Studio,可以完成创建、调试、修改应用程序等的各种操作。

VC++6.0提供面向对象技术的支持,它能够帮助使用MFC库的用户自动生成一个具有图形界面的应用程序框架。

用户只需在该框架的适当部分添加、扩充代码就可以得到一个满意的应用程序。

VC++6.0除了包含文本编辑器,C/C++混合编译器,连接器和调试器外,还提供了功能强大的资源编辑器和图形编辑器,利用“所见即所得”的方式完成程序界面的设计,大大减轻程序设计的劳动强度,提高程序设计的效率。

VC++的功能强大,用途广泛,不仅可以编写普通的应用程序,还能很好地进行系统软件设计及通信软件的开发。

二、使用Visual C++ 6.0建立C语言应用程序利用VC++6.0提供的一种控制台操作方式,可以建立C语言应用程序,Win32控制台程序(Win32 Console Application)是一类Windows程序,它不使用复杂的图形用户界面,程序与用户交互是通过一个标准的正文窗口,下面我们将对使用Visual C++ 6.0编写简单的C语言应用程序作一个初步的介绍。

1.安装和启动运行Visual Studio软件中的setup.exe程序,选择安装Visual C++ 6.0,然后按照安装程序的指导完成安装过程。

安装完成后,在开始菜单的程序选单中有Microsoft Visual Studio 6.0图标,选择其中的Microsoft Visual C++ 6.0即可运行(也可在Window桌面上建立一个快捷方式,以后双击即可运行)。

VC++6.0使用简介

VC++6.0使用简介

C++程序设计开发环境C++程序设计开发环境操作系统:Windows 2000 Server/Xp/Professional集成开发环境:VC++ 6.0微机:486或以上1、选择“开始”菜单的“程序”2、选择”程序”中的“Microsoft Visual Studio 6.0”,再选择其下的“Microsoft Visual C++ 6.0”,单击后进入VC++6.0的集成开发环境。

第一个标准C++程序在VC++ 6.0集成开发环境下编写运行第一个标准C++程序1、首先创建新工程。

具体步骤如下:a)选择“File”菜单中的“New”选项,单击后显示New对话框b) 单击“Projects”标签,在其中单击“Win32 Console Application”(win32标准控制台程序)i.在“Project name”框中输入一个工程名(用户自己定义工程名),如上experiment,在“Location”框中输入工程存放路径,也可按默认路径存放。

ii.也可点击右边的…按纽,通过鼠标选择工程存放路径(建议采用该方法设置工程存放路径),如下图iii.单击”ok”按钮,弹出下图c)选择An empty project单选项,单击”finish”,弹出下图d)单击“ok”按钮,完成项目创建过程。

2、建立C++源程序文件a) 选择“File”菜单中的“New”选项,单击后显示New对话框b) 单击“Files”标签,在其中单击“C++ Source File”(C++源程序文件)i. 选中“Add to project”复选框,框中工程名为我们刚刚新建的工程“experiment”。

ii. 在“File”框中输入一个文件名(用户自己定义C++源程序名),如上图first,“Location”框中按默认路径存放。

iii. 单击“ok”,完成新建C++源程序文件,弹出下图。

3、编辑C++源程序文件a)在上图的文件编辑窗口中输入程序源代码。

VC6使用技巧及问题收集

VC6使用技巧及问题收集

VC6使用技巧及问题收集VC6使用技巧及问题收集 - [技术文摘]自己收集、综合了一些网上流传的文章,像原创者致意1.检测程序中的括号是否匹配把光标移动到需要检测的括号(如大括号{}、方括号[]、圆括号()和尖括号<>)前面,键入快捷键“Ctrl+]”。

如果括号匹配正确,光标就跳到匹配的括号处,否则光标不移动,并且机箱喇叭还会发出一声警告声。

[注:当一个函数体的内容过长时,全部选中,可以把光标移动到函数体的{处,按下"Ctrl+Shift+]",即可全部选中]2.格式化一段乱七八糟的源代码选中那段源代码,按Alt+F8。

[另:选中一段代码,按下Tab(或shift+Tab),右(或左)移一个Tab]3.如何整理ClassView视图中大量的类可以在classview 视图中右键新建文件夹(new folder),再把具有相近性质的类拖到对应的文件夹中,使整个视图看上去清晰明了。

[注:事实上,我也见到在FileView里用文件夹分类的,我的感觉是:可能是为了避免在Classviews里出现如上述的部分函数丢失的情况吧,毕竟VC6有时并不是很稳定,当然这两种方法各有利弊的,我目前一般是倾向于前者的]4.在编辑状态下发现成员变量或函数不能显示删除该项目扩展名为.ncb文件,重新打开该项目。

[注:不要删除.opt文件,因为里面可能存有你在Classview新建的文件夹信息,删除的话那些分类文件夹信息也一并删除了]5.如何添加系统中的头文件(.h)到当前项目。

使用#include ,告诉编译到VC系统目录去找;使用#include "FileName.h",告诉编译在当前目录找。

6.如何干净的删除一个类先从Workspace中的FileView中删除对应的.h和.cpp文件,再关闭项目,从实际的文件夹中删除对应的.h和.cpp文件与.clw文件。

------------------------------7.定位预处理指令在源文件中定位光标到对称的#if、 #endif,使用Ctrl+K。

修改core file size-概述说明以及解释

修改core file size-概述说明以及解释

修改core file size-概述说明以及解释1.引言1.1 概述在撰写此篇长文之前,我们首先需要了解什么是core file size以及为什么需要修改它。

Core file size指的是在发生程序崩溃或异常退出时,系统生成的core文件的大小限制。

正常情况下,core文件包含了程序崩溃时的内存状态、堆栈信息以及其他调试相关的数据,这对于开发人员来说是非常有价值的。

通过分析core文件,开发人员可以更容易地定位和解决问题。

默认情况下,操作系统对core文件的大小有一定的限制。

一旦core 文件大小达到了限制,系统会停止继续生成core文件,从而保护系统的稳定性和性能。

然而,在某些情况下,我们可能需要修改core file size 的限制,以便能够生成更大的core文件,以提供更详细的调试信息。

本文将讨论如何修改core file size的方法,以及对此操作可能带来的意义和影响。

在修改core file size之前,我们需要了解系统的具体配置和限制,并采取相应的步骤来修改系统设置。

同时,我们还将讨论可能的风险和注意事项,以确保在修改core file size时不会对系统的稳定性和安全性产生负面影响。

通过对core file size的修改,开发人员可以更充分地利用core文件提供的调试信息来定位和解决程序的问题。

然而,这也需要在操作系统的限制下谨慎操作,以确保系统的稳定性和性能不受影响。

在深入探讨修改core file size的方法之前,我们需要先了解当前系统的配置和限制,以便做出明智的决策并采取必要的措施。

接下来,本文将详细介绍好几种修改core file size的方法,并逐一讨论它们的优缺点和适用场景。

这将帮助读者根据实际需求选择最合适的方法来修改core file size。

在总结部分,我们将对本文的主要内容进行回顾,并强调修改core file size的重要性和潜在影响。

C++中使用内存映射文件处理大文件

C++中使用内存映射文件处理大文件

C++中使⽤内存映射⽂件处理⼤⽂件引⾔ ⽂件操作是应⽤程序最为基本的功能之⼀,Win32 API和MFC均提供有⽀持⽂件处理的函数和类,常⽤的有Win32 API的CreateFile()、WriteFile()、ReadFile()和MFC提供的CFile类等。

⼀般来说,以上这些函数可以满⾜⼤多数场合的要求,但是对于某些特殊应⽤领域所需要的动辄⼏⼗GB、⼏百GB、乃⾄⼏TB的海量存储,再以通常的⽂件处理⽅法进⾏处理显然是⾏不通的。

⽬前,对于上述这种⼤⽂件的操作⼀般是以内存映射⽂件的⽅式来加以处理的,本⽂下⾯将针对这种Windows核⼼编程技术展开讨论。

内存映射⽂件 内存映射⽂件与虚拟内存有些类似,通过内存映射⽂件可以保留⼀个地址空间的区域,同时将物理存储器提交给此区域,只是内存⽂件映射的物理存储器来⾃⼀个已经存在于磁盘上的⽂件,⽽⾮系统的页⽂件,⽽且在对该⽂件进⾏操作之前必须⾸先对⽂件进⾏映射,就如同将整个⽂件从磁盘加载到内存。

由此可以看出,使⽤内存映射⽂件处理存储于磁盘上的⽂件时,将不必再对⽂件执⾏I/O操作,这意味着在对⽂件进⾏处理时将不必再为⽂件申请并分配缓存,所有的⽂件缓存操作均由系统直接管理,由于取消了将⽂件数据加载到内存、数据从内存到⽂件的回写以及释放内存块等步骤,使得内存映射⽂件在处理⼤数据量的⽂件时能起到相当重要的作⽤。

另外,实际⼯程中的系统往往需要在多个进程之间共享数据,如果数据量⼩,处理⽅法是灵活多变的,如果共享数据容量巨⼤,那么就需要借助于内存映射⽂件来进⾏。

实际上,内存映射⽂件正是解决本地多个进程间数据共享的最有效⽅法。

内存映射⽂件并不是简单的⽂件I/O操作,实际⽤到了Windows的核⼼编程技术--内存管理。

所以,如果想对内存映射⽂件有更深刻的认识,必须对Windows操作系统的内存管理机制有清楚的认识,内存管理的相关知识⾮常复杂,超出了本⽂的讨论范畴,在此就不再赘述,感兴趣的读者可以参阅其他相关书籍。

vc6 多文件编译方法

vc6 多文件编译方法

vc6 多文件编译方法一、什么是多文件编译多文件编译是指将一个程序拆分成多个源文件进行编译,然后再将编译后的目标文件链接起来生成可执行文件。

这种方法可以提高代码的可读性和维护性,使程序的开发更加灵活和高效。

二、多文件编译的步骤1. 创建工程在VC6中,首先需要创建一个工程,选择“文件”菜单下的“新建”->“项目”->“Win32控制台应用程序”,然后填写工程名称和存放路径,点击“确定”按钮即可创建一个新的工程。

2. 添加源文件在创建好的工程中,可以通过“项目”菜单下的“添加到项目”选项来添加源文件。

选择“添加到项目”后会弹出一个对话框,在对话框中选择要添加的源文件并点击“确定”按钮即可将源文件添加到工程中。

3. 设置编译选项在VC6的工具栏中,点击“项目”->“设置”菜单项,弹出的对话框中选择“链接”选项卡,然后在“项目文件”列表中选择要编译的源文件。

在“设置”对话框中,还可以设置编译器的相关选项,如编译器的优化级别、生成调试信息等。

4. 编译工程在设置好编译选项后,点击工具栏上的“生成”按钮或选择“生成”->“生成解决方案”菜单项来开始编译工程。

编译过程中,VC6会逐个编译源文件,并生成对应的目标文件。

5. 链接目标文件编译完成后,VC6会自动调用链接器将所有的目标文件链接起来生成可执行文件。

链接器会根据代码之间的引用关系来解析符号,并将它们连接在一起。

6. 运行程序链接完成后,可以通过点击工具栏上的“运行”按钮或选择“调试”->“开始执行”菜单项来运行程序。

VC6会自动启动调试器,并执行生成的可执行文件。

三、常见问题及解决方法1. 无法找到源文件在添加源文件时,如果出现“无法找到源文件”的错误提示,可以检查源文件是否在指定的路径下,并确保路径名称的正确性。

2. 编译错误在编译过程中,可能会出现各种编译错误,如语法错误、类型不匹配等。

这时需要仔细检查错误信息,并逐个解决错误。

减小VC6生成的exe体积

减小VC6生成的exe体积

减小VC6生成的exe体积通常vc++编译出来的程序体积很大,debug模式的程序的最小体积一般都在100KB以上。

这使不少人对VC++有了不好的印象,以为VC++是制造麻烦的工具。

其实情况并不是这样,我们可以通过一些办法有效的减少执行程序的体积。

下面通过一个具体的范例给你讲述:1,首先我们打开vc++建立一个Win32 Application,工程名随便,接下来选择“a Typical "hello World" application”(因为是范例,所以以hello world为标准)2,选择编译方式为Win32 - Release. 这时候你编译程序,生成的执行程序是28kb(如果你的机器感染了病毒,体积可能会大一些,如果我的机器感染了病毒,而你的机器正常,你的执行程序可能会小一些...这些全都是废话)3,选择菜单:Project->Settings(或者按Alt+F7),打开Link 属性页。

将Object/library modules:下面编辑框中的各种lib全部删除,然后打上MSVCRT.LIB kernel32.lib user32.lib此后编译程序,生成的执行程序为20kb(此时编译程序会出现警告:LINK : warning LNK4098: default lib "LIBC" conflicts with use of other libs; use /NODEFAULTLIB:library不必理会,如果你想去掉警告,就在Ignore all default libraries 前打勾)4,接着上面,在Project->Settings的Link属性页里,在Project Options下面的编辑框里加上一句:/ALIGN:4096 这样做之后指定了程序不是驱动程序此后编译程序,生成的执行程序为7KB至此给Win32 Application减肥告一段落,7KB的程序另我满意了,如果你觉得还能减,不妨再做一些别的尝试,等你的好消息:)减肥总结:选择恰当的编译模式,去掉不必要的库。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

VC6++内存映射修改大文件方法本文介绍利用VC6++内存映射文件修改大文件的方法:在大文件内存前加入一段数据,若要使用内存映射文件,必须执行下列操作步骤:1.创建或打开一个文件内核对象,该对象用于标识磁盘上你想用作内存映射文件的文件;2.创建一个文件映射内核对象,告诉系统该文件的大小和你打算如何访问该文件;3.让系统将文件映射对象的全部或一部分映射到你的进程地址空间中;当完成对内存映射文件的使用时,必须执行下面这些步骤将它清除:1.告诉系统从你的进程的地址空间中撤消文件映射内核对象的映像;2.关闭文件映射内核对象;3.关闭文件内核对象;下面将用一个实例详细介绍这些操作步骤。

一、我们打开关于A文件内核对象,并创建一个关于B文件的内核对象若要创建或打开一个文件内核对象,总是要调用CreateFile函数:HANDLE CreateFile(PCSTR pszFileName,DWORD dwDesiredAccess,DWORD dwShareMode,PSECURITY_ATTRIBUTES psa,DWORD dwCreationDisposition,DWORD dwFlagsAndAttributes,HANDLE hTemplateFile);CreateFile函数拥有好几个参数,这里只重点介绍前3个参数,即szFileName,dwDesiredAccess和dwShareMode。

你可能会猜到,第一个参数pszFileName 用于指明要创建或打开的文件的名字(包括一个选项路径),第二个参数dwDesiredAccess 用于设定如何访问该文件的内容,可以设定下表所列的4个值中的一个。

当创建或打开一个文件,将它作为一个内存映射文件来使用时,请选定最有意义的一个或多个访问标志,以说明你打算如何访问文件的数据,对内存映射文件来说,必须打开用于只读访问或读写访问的文件,因此,可以分别设定GENERIC_READ或GENERIC_READ|GENERIC_WRITE, 第三个参数dwShareMode告诉系统你想如何共享该文件,可以为dwShareMode设定下表所列的4个值之一:如果CreateFile函数成功地创建或打开指定的文件,便返回一个文件内核对象的句柄,否则返回INVALID_HANDLE_VALUE, 注意能够返回句柄的大多数Windows函数如果运行失败,那么就会返回NULL,但是,CreateFile函数将返回INVALID_HANDLE_VALUE,它定义为((HANDLE)-1),HANDLEhFile=CreateFile(".\\first.txt",GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_E XISTING,FILE_FLAG_SEQUENTIAL_SCAN,NULL);HANDLEhmyfile=CreateFile("E:\\my.txt",GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL ,NULL);二、我们要分别创建两个文件映射内核对象调用CreateFile函数,就可以将文件映像的物理存储器的位置告诉操作系统,你传递的路径名用于指明支持文件映像的物理存储器在磁盘(或网络或光盘)上的确切位置,这时,必须告诉系统,文件映射对象需要多少物理存储器,若要进行这项操作,可以调用CreateFileMapping函数:HANDLE CreateFileMapping(HANDLE hFile,PSECURITY_ATTRIBUTES psa,DWORD fdwProtect,DWORD dwMaximumSizeHigh,DWORD dwMaximumSizeLow,PCTSTR pszName);第一个参数hFile用于标识你想要映射到进程地址空间中的文件句柄,该句柄由前面调用的CreateFile函数返回,psa参数是指向文件映射内核对象的SECURITY_ATTRIBUTES结构的指针,通常传递的值是NULL(它提供默认的安全特性,返回的句柄是不能继承的)。

本章开头讲过,创建内存映射文件就像保留一个地址空间区域然后将物理存储器提交给该区域一样,因为内存映射文件的物理存储器来自磁盘上的一个文件,而不是来自从系统的页文件中分配的空间,当创建一个文件映射对象时,系统并不为它保留地址空间区域,也不将文件的存储器映射到该区域(下一节将介绍如何进行这项操作),但是,当系统将存储器映射到进程的地址空间中去时,系统必须知道应该将什么保护属性赋予物理存储器的页面,CreateFileMapping函数的fdwProtect参数使你能够设定这些保护属性,大多数情况下,可以设定下表中列出的3个保护属性之一。

使用fdwProtect参数设定的部分保护属性在Windows98下,可以将PAGE_WRITECOPY标志传递给CreateFileMapping,这将告诉系统从页文件中提交存储器,该页文件存储器是为数据文件的数据拷贝保留的,只有修改过的页面才被写入页文件,你对该文件的数据所作的任何修改都不会重新填入原始数据文件,其最终结果是,PAGE_WRITECOPY标志的作用在Windows2000和Windows98上是相同的。

除了上面的页面保护属性外,还有4个节保护属性,你可以用OR将它们连接起来放入CreateFileMapping函数的fdwProtect参数中,节只是用于内存映射的另一个术语。

节的第一个保护属性是SEC_NOCACHE,它告诉系统,没有将文件的任何内存映射页面放入高速缓存,因此,当将数据写入该文件时,系统将更加经常地更新磁盘上的文件数据,这个标志与PAGE_NOCACHE保护属性标志一样,是供设备驱动程序开发人员使用的,应用程序通常不使用,Windows98将忽略SEC_NOCACHE标志。

节的第二个保护属性是SEC_IMAGE,它告诉系统,你映射的文件是个可移植的可执行(PE)文件映像,当系统将该文件映射到你的进程的地址空间中时,系统要查看文件的内容,以确定将哪些保护属性赋予文件映像的各个页面,例如,PE文件的代码节(.text)通常用PAGE_EXECUTE_READ属性进行映射,而PE文件的数据节(.data)则通常用PAGE_READWRITE属性进行映射,如果设定的属性是SEC_IMAGE,则告诉系统进行文件映像的映射,并设置相应的页面保护属性。

Windows98将忽略SEC_IMAGE标志最后两个保护属性是SEC_RESERVE和SEC_COMMIT,它们是两个互斥属性,当使用内存映射数据文件时,它们不能使用,这两个标志将在本章后面介绍,当创建内存映射数据文件时,不应该设定这些标志中的任何一个标志,CreateFileMapping将忽略这些标志。

CreateFileMapping的另外两个参数是dwMaximumSizeHigh和dwMaximumSizeLow,它们是两个最重要的参数,CreateFileMapping函数的主要作用是保证文件映射对象能够得到足够的物理存储器,这两个参数将告诉系统该文件的最大字节数,它需要两个32位的值,因为Windows支持的文件大小可以用64位的值来表示,dwMaximumSizeHigh参数用于设定较高的32位,而dwMaximumSizeLow参数则用于设定较低的32位值,对于4GB或小于4GB的文件来说,dwMaximumSizeHigh的值将始终是0。

使用64位的值,意味着Windows能够处理最大为16EB(1018字节)的文件,如果想要创建一个文件映射对象,使它能够反映文件当前的大小,那么可以为上面两个参数传递0,如果只打算读取该文件或者访问文件而不改变它的大小,那么为这两个参数传递0,如果打算将数据附加给该文件,可以选择最大的文件大小,以便为你留出一些富裕的空间,如果当前磁盘上的文件包含0字节,那么可以给CreateFileMapping函数的dwMaximumSizeHigh 和dwMaximumSizeLow传递两个0,这样做就可以告诉系统,你要的文件映射对象里面的存储器为0字节,这是个错误,CreateFileMapping将返回NULL。

如果你对我们讲述的内容一直非常关注,你一定认为这里存在严重的问题,Windows 支持最大为16EB的文件和文件映射对象,这当然很好,但是,怎样将这样大的文件映射到32位进程的地址空间(32位地址空间是4GB文件的上限)中去呢,下一节介绍解决这个问题的办法,当然,64位进程拥有16EB的地址空间,因此可以进行更大的文件的映射操作,但是,如果文件是个超大规模的文件,仍然会遇到类似的问题。

若要真正理解CreateFile和CreateFileMapping两个函数是如何运行的,建议你做一个下面的实验,建立下面的代码,对它进行编译,然后在一个调试程序中运行它,当你一步步执行每个语句时,你会跳到一个命令解释程序,并执行C:\目录上的“dir”命令,当执行调试程序中的每个语句时,请注意目录中出现的变化。

int WINAPI _tWinMain(HINSTANCE hinstExe, HINSTANCE,PTSTR pszCmdLine, int nCmdShow){//Before executing the line below, C:\ does not have//a file called "MMFTest.Dat."HANDLE hfile = CreateFile("C:\\MMFTest.dat",GENERIC_READ | GENERIC_WRITE,FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL, NULL);//Before executing the line below, the MMFTest.Dat//file does exist but has a file size of 0 bytes.HANDLE hfilemap = CreateFileMapping(hfile, NULL, PAGE_READWRITE, 0, 100, NULL);//After executing the line above, the MMFTest.Dat//file has a size of 100 bytes.//CleanupCloseHandle(hfilemap);CloseHandle(hfile);//When the process terminates, MMFTest.Dat remains//on the disk with a size of 100 bytes.return(0);}如果调用CreateFileMapping函数,传递PAGE_READWRITE标志,那么系统将设法确保磁盘上的相关数据文件的大小至少与dwMaximumSizeHigh和dwMaximumSizeLow参数中设定的大小相同,如果该文件小于设定的大小,CreateFileMapping函数将扩展该文件的大小,使磁盘上的文件变大,这种扩展是必要的,这样,当以后将该文件作为内存映射文件使用时,物理存储器就已经存在了,如果正在用PAGE_READONLY或PAGE_WRITECOPY标志创建该文件映射对象,那么CreateFileMapping特定的文件大小不得大于磁盘文件的物理大小,这是因为你无法将任何数据附加给该文件。

相关文档
最新文档