前面我们讲过内存映射文件的使用,但是,如果文件大小超过内存大小那怎么办呢
其实,我们在把内存映射文件映射到进程的地址空间时,可以映射一部分,通过一个循环,把整个文件处理完
下面我举个例子
#include <windows.h>
#include <iostream>
#include <stdio.h>
using namespace std;
__int64 Count0s();
int main()
{
__int64 co=Count0s();
//cout<<co<<endl;
printf("%I64u",co);
system("pause");
return 0;
}
__int64 Count0s()
{
SYSTEM_INFO si;
GetSystemInfo(&si);
//打开数据文件
HANDLE hFile=CreateFile("FuncMan.dat",GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_FLAG_SEQUENTIAL_SCAN,NULL);
if(hFile==INVALID_HANDLE_VALUE)
{
cout<<"打开文件失败"<<endl;
return 0;
}
//创建文件映射对象
HANDLE hFileMap=CreateFileMapping(hFile,NULL,PAGE_READONLY,0,0,NULL);
if(hFileMap==NULL)
{
CloseHandle(hFile);
cout<<"创建文件映射对象失败"<<endl;
return 0;
}
//获取文件大小
DWORD FileSizeHigh,FileSizeLow;
FileSizeLow=GetFileSize(hFile,&FileSizeHigh);
//在这里如果想要获取超过4GB文件的大小
__int64 FileSize=FileSizeLow+(FileSizeHigh<<32);
CloseHandle(hFile);
__int64 FileOffSet=0,NumOf0s=0;
DWORD dwBytesInBlock;
while(FileSize>0)
{
dwBytesInBlock=si.dwAllocationGranularity;
if(FileSize<si.dwAllocationGranularity)
{
dwBytesInBlock=(DWORD)FileSize;
}
PBYTE pbFile=(PBYTE)MapViewOfFile(hFileMap,FILE_MAP_READ,(DWORD)(FileOffSet>>32),(DWORD)(FileOffSet&0xFFFFFFFF),dwBytesInBlock);
for(DWORD dwByte=0;dwByte<dwBytesInBlock;dwByte++)
{
if(pbFile[dwByte]==0)
{
NumOf0s++;
}
}
UnmapViewOfFile(pbFile);
FileOffSet+=dwBytesInBlock;
FileSize-=dwBytesInBlock;
}
CloseHandle(hFileMap);
return NumOf0s;
}
这里需要注意的是文件的位移一定需要是分配粒度的倍数,所以,当所剩的大小大于分配粒度时 dwBytesInBlock等于分配粒度,否则等于文件剩下的大小
测试结果:
4796