使用內存映射文件處理大文件示例

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

下面我舉個例子

#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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章