Visual c++ 内存映射文件代码在C++;

Visual c++ 内存映射文件代码在C++;,visual-c++,file-io,memory-mapped-files,Visual C++,File Io,Memory Mapped Files,我试图通过将大文件映射到内存来读取它们,以提高效率。在打开文件、创建内存映射对象和视图之后,我试图通过取消引用指向内存的指针来访问文件中的值,但无法获得文件中的实际值 对于一个小实验,我尝试读取以下文件“test.txt”中的值,该文件包含4个整数作为 1 2 34 这是我的密码 HANDLE hCreateFile; HANDLE hMapFile; LPVOID lpMapAddress; char tempFile[200]; strcpy(tempFile,"C:\\...\\test.

我试图通过将大文件映射到内存来读取它们,以提高效率。在打开文件、创建内存映射对象和视图之后,我试图通过取消引用指向内存的指针来访问文件中的值,但无法获得文件中的实际值

对于一个小实验,我尝试读取以下文件“test.txt”中的值,该文件包含4个整数作为 1 2 34

这是我的密码

HANDLE hCreateFile;
HANDLE hMapFile;
LPVOID lpMapAddress;
char tempFile[200];
strcpy(tempFile,"C:\\...\\test.txt");
hCreateFile = CreateFile(tempFile,GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);   //Opens the "tempFile" and returns an handle to the file

if(hCreateFile == INVALID_HANDLE_VALUE) {
    std::cout<<"Problem opening the file"<<std::endl;
}

hMapFile = CreateFileMapping(hCreateFile, NULL, PAGE_READONLY, 0, 0, 0);
if(hMapFile == 0)   {
    std::cout<<"Problem creating map file object"<<std::endl;
}

lpMapAddress = MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 0);
if(lpMapAddress == 0){
    std::cout<<"Problem viewing the file"<<std::endl;
}

int* mp = (int*)lpMapAddress;
std::cout<<"The first dose value is "<<*mp<<" ";
std::cout<<"The second dose value is "<<*(mp+1)<<" ";
std::cout<<"The third dose value is "<<*(mp+2)<<" ";
std::cout<<"The fourth dose value is "<<*(mp+3)<<;
处理hCreateFile;
处理hMapFile;
LPVOID lpMapAddress;
char tempFile[200];
strcpy(tempFile,“C:\\…\\test.txt”);
hCreateFile=CreateFile(临时文件,通用读取,0,NULL,打开现有,文件属性,NULL)//打开“tempFile”并返回该文件的句柄
if(hCreateFile==无效的\u句柄\u值){

std::cout看起来您正在读取ASCII数据,并期待一个神奇的整数转换

思考一下文本是什么:

“1234”

现在,您的第一个值是:221388849

测试代码为0x0D322031

0x31=“1” 0x20=“” ox32=“2”


…等等。

使用文件映射API读取简单文本文件听起来不太好。掌握如何读取简单文本文件-使用更简单的函数,如
fopen
/
fscanf
ifstream
类。然后了解如何使用
CreateFile
ReadFile
读取相同的文件。使用除非您了解什么是文本文件,什么是二进制文件(实际上什么都不是,只是如何打开文件),否则文件映射是一个大禁忌

若要以文本模式打开文件,请使用带有t选项的
fopen
(此功能的默认设置)。若要以二进制模式打开文件,需要明确指定b模式

存储在文件中的数字
1
并不意味着值1。它实际上是49。因为
1
的ASCII是整数49。您正在尝试以整数形式读取此值(一个字节)。整数是4字节(一般化,并根据您的情况假设)。其中剩余的3个字节将是垃圾(哪三个-前三个或后三个-你算出来!!)。只有一个字节(int-4字节的第一个或最后一个)将是
1
的值为49。在一个、两个或四个字节的整数中永远不会得到
1
(你只能得到49)

由于“1 2 3 4”存储在文件“1”(49)中,所以存储了空格(ASCII 32)

49,32,50,32,51,32

将前四个字节解析为这个整数(在程序员模式下使用Windows7计算器)


有很多东西需要理解…

似乎您正在尝试将字符值读取为Int值。由于Int是4字节(通常),那么*mp将是“1”、“2”和“”的四个ascii值的组合。请注意,“1”的ascii值不是1。*(mp+1)将是“3”、“4”和“”。然后最后两个值为null。顺便说一句-这个问题似乎与是否使用内存映射文件无关。@Steven Hansen我知道mp对应于“1”、“2”和“”。因此,在这种情况下,我是否需要在取消引用它们时使用char指针,然后将其强制转换为int?例如,char mp=(char*)lpMapAddress,然后是int(*mp)?谢谢。如果您有个位数,您可以使用char*,但不能将它们转换为int。您可能应该使用atoi系列中的一个函数,它也支持多个位数的数字。@StevenHansen感谢Steven、Bubbafat和Ajay的评论。我可以使用内存映射文件来映射大的files(整数或双精度)进入内存,并从内存中读取它们,而不是使用ifstream类。这使双文件的加速比提高了5倍,int文件的加速比提高了15倍,这正是我想要看到的。您的评论有助于我正确读取数据。再次感谢。好的,从您和Steven的评论中,我了解到*mp是“1”、“2”、“2”的组合。那么,221388849是否与此对应?我不明白那部分。谢谢。我解释了221388849是什么。你不明白什么?数字存储在小尾端。从头读。续集是3420330A,这意味着你有一个介于2和3之间的CRLF。@Ajay Ok。我试图读取的文本文件是大约40 MB,包括多行整数数据。现在,我将每行作为一个字符串,然后使用istringstream类将字符串解析为整数,然后将每个整数值添加到其向量中(即,每行有一个对应的向量)。现在,所有这些都需要大约10秒,但我希望加快速度(需要10次)。因此,我认为我可以使用我所知甚少的内存映射文件。@下面是我的代码,那么有没有一种不使用映射内存文件读取数据的更快方法?或者这是这种情况下的唯一方法?感谢您的帮助。std::ifstream input;input.open(tempFile);I=0;while(getline(input,s)){std::istringstream ss(s);而(std::getline(ss,r,,','){std::stringstream convert(r);//将r转换为int y convert>>y;b[i].setv(y);//b是对象的向量。b[i]是int的向量(每个y被推回到向量)}i++;//i对应于每一行}内存映射文件的读取速度并不比
ReadFile
API快。加速取决于许多因素:调试或发布版本、在一次API调用中读取的数据量、磁盘的速度(和碎片整理状态)。字符串读取和解析是第二个方面。不要混用!