c++ 利用内存映射读取大文件
由于用到的txt存放的数据有几十万行,用getline来读取文件非常慢,搜索了一下可以来优化读取文件的方法。
据说用内存映射读取文件速度快,试了一下,但是发现要分行处理数据时,速度还是挺慢的。
有关内存映射的介绍,参考别人博客。
http://blog.csdn.net/wcyoot/article/details/7363393
///////////////////////////////////////////////////////////////////////////// ///创建镜像文件来读取文件,提高速度 /////////////////////////////////////////////////////////////////////////// void useMapFileReadText(){ HANDLE hFile = NULL, hFileMap = NULL; char * lpbMapAddress = NULL; int nFileSize = 0, nLeftSize = 0; if(hFile == NULL) { hFile = CreateFile("data.txt", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if(hFile == INVALID_HANDLE_VALUE) { printf("打开文件失败"); } } if(hFileMap == NULL) { hFileMap=CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL); if(hFileMap==NULL) { OutputDebugString("文件镜像句柄创建失败!"); CloseHandle(hFile); } } if(lpbMapAddress == NULL) { lpbMapAddress = (char *)MapViewOfFile(hFileMap, FILE_MAP_READ, 0, 0, 0); if(lpbMapAddress == NULL) { OutputDebugString("内存映射文件失败!"); CloseHandle(hFileMap); CloseHandle(hFile); } } const char* buf = lpbMapAddress; const char* start = lpbMapAddress; int len; while(start != NULL){ start = _get_line(buf, &len); string str(buf,len); //////////////do something with str buf = start; } //释放 UnmapViewOfFile(hFile); CloseHandle(hFileMap); }
其中的,_get_line 函数
" " 在windows中为0x0d 0x0a 占两个字符,在linux系统中为0x0a占一个字符。
//buf:从当前地址开始搜索。 //len: 存放该行的字符串长度,不包含回车换行符。 //返回值:下一次搜索开始的地址.如果到达文件尾,则返回NULL const char* _get_line(const char* buf, int* len) { const char* tmp = buf; while(*tmp && (*tmp != 0x0d && *tmp != 0x0a && *tmp != " ")) ++tmp; //while(*tmp && (*tmp != 0x0d || *tmp != 0x0a )) ++tmp; *len = tmp - buf; // if (*tmp == 0) return NULL; // skip New-Line char if (*tmp == 0x0d){ // Windows style New-Line 0x0d 0x0a tmp += 2; //assert(*tmp == 0x0a); }//else Unix style New-Line 0x0a else{ ++tmp; } return tmp; }
用十三万多行来测试,这样按行来处理时,不如getiline速度快。
内存映射的优势还是在于大文件。
fstream.open() 时,由于文件太大,IO一次读不了所有的数据,需要多次IO操作。
而内存映射,并不是将文件加载到内存。内存映射首先申请一段地址空间,并映射到物理存储器,而这里的物理存储器就是文件所在的磁盘,类似虚拟内存(pagefile);
当有需要时,程序不需要先把它加到内存,而是直接从磁盘读取。这样就减少了IO操作。
内存映射的一个优势还在于多个进程之间共享数据。
声明:该文观点仅代表作者本人,牛骨文系教育信息发布平台,牛骨文仅提供信息存储空间服务。
- 上一篇: React 组件的三种写法总结
- 下一篇: js+php微信扫码支付详细说明+demo