前面我們講過內存映射文件的使用,但是,如果文件大小超過內存大小那怎麼辦呢
其實,我們在把內存映射文件映射到進程的地址空間時,可以映射一部分,通過一個循環,把整個文件處理完
下面我舉個例子
#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