用内存映射的方式打开大文件

最近需要每次读写2TB的数据,所以找了种方法来解决。希望对大家对于读取打文件有所了解。或许哪天就能用的到。

 

HANDLE m_handle_file = CreateFile(strFilePath,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
    if(m_handle_file == INVALID_HANDLE_VALUE)
    {
        TRACE("%d\r\n",GetLastError());
        CloseHandle(m_handle_file);
        return;
    }
    //创建文件映射对象
    HANDLE m_handle_map = CreateFileMapping(m_handle_file,NULL,PAGE_READWRITE,0,0,NULL);
    if(m_handle_map == NULL)
    {
        TRACE("%d\r\n",GetLastError());
        CloseHandle(m_handle_map);
        return;
    }
   

    //获得系统分配的粒度
    SYSTEM_INFO    m_systeminfo;
    GetSystemInfo(&m_systeminfo);
    DWORD dwGran = m_systeminfo.dwAllocationGranularity;
    DWORD dwFileSizeHigh;

    __int64 qwFileSize = GetFileSize(m_handle_file,&dwFileSizeHigh);
    qwFileSize |= (((__int64)dwFileSizeHigh) << 32);
    CloseHandle(m_handle_file);
    //偏移地址
    __int64 qwFileOfSet = 0;
    DWORD dwBlocByte = dwGran;
    while(qwFileSize > 0)
    {
        if(    qwFileSize < dwBlocByte)
        {
            dwBlocByte = (DWORD)qwFileSize;//如果小于则为实际大小
        }
        //映射视图
        LPBYTE lpMapAddress = (LPBYTE)MapViewOfFile(m_handle_map,FILE_MAP_ALL_ACCESS,(DWORD)(qwFileOfSet >> 32),(DWORD)(qwFileOfSet & 0xFFFFFFFF),dwBlocByte);
        if(lpMapAddress == NULL)
        {
            TRACE("%d\r\n",GetLastError());
            CloseHandle(m_handle_map);
            return;
        }
        //对映射视图进行访问
        /*for(DWORD i = 0; i < dwBlocByte; i++)
        {
            BYTE temp = *(lpMapAddress + i);
        }*/
        //撤销文件映像
        UnmapViewOfFile(lpMapAddress);
        qwFileOfSet += dwBlocByte;
        qwFileSize -= dwBlocByte;
    }
   
    CloseHandle(m_handle_map);

 

下面这些函数被应用于文件内存映射中:
1) CreateFileMapping
2) FlushViewOfFile
3) MapViewOfFile
4) MapViewOfFileEx
5) MapViewOfFileVlm
6) OpenFileMapping
7) UnmapViewOfFile
8) UnmapViewOfFileVlm
函数详细说明:
一、CreateFileMapping 为指定文件创建一个有名或无名的文件映象;
HANDLE CreateFileMapping(
HANDLE hFile, // 映射文件的句柄
LPSECURITY_ATTRIBUTES lpFileMappingAttributes,
// 安全描述符指针
DWORD flProtect, // 对映射对象的保护
DWORD dwMaximumSizeHigh, // 对象最大长度的高32位
DWORD dwMaximumSizeLow, // 对象最大长度的低32位
LPCTSTR lpName // 文件内存映射对象的名字
);
注意:
hFile:映射文件的句柄,文件的打开模式必须与flProtect参数指定的相一致;如果这个参数值为0xFFFFFFFF,那么必须在dwMaximumSizeHigh和dwMaximumSizeLow参数中指定映射对象的大小。并且将在操作系统虚拟内存页面替换文件中创建文件映射对象,而不是使用磁盘文件,同时必须给出这个映射对象的大小。文件映射对象通过副本,遗传或名字来共享。
lpFileMappingAttributes:安全描述符指针,决定返回句柄是否能被子进程继承,如果是NULL,那么子进程不能继承。WinNt中,如果是NULL,那么文件映射对象得到一个默认的安全描述符。
flProtect:为得到的文件试图指定保护模式,可以被设置为下列值:
PAGE_READONLY :只读属性,并且hFile对应的文件必须以GENERIC_READ形式打开。
PAGE_READWRITE:可读可写属性,并且hFile对应的文件必须以GENERIC_READ 和 GENERIC_WRITE形式打开。
PAGE_WRITECOPY:对可写区域复制后操作,并且hFile对应的文件必须以GENERIC_READ 和 GENERIC_WRITE形式打开。
dwMaximumSizeHigh,dwMaximumSizeLow:如果这两个参数为0,则文件映射对象的最大长度等于hFile指定的文件长度。
lpName:文件映射对象的名字,如果这个名字已存在,则按照flProtect指定的来处理映射对象。如果此参数为空,则创建一个无名字的文件映射对象。如果此参数的名字与系统事件的名字相同,则函数执行失败,GetLastError返回 ERROR_INVALID_HANDLE;
返回值:函数调用成功返回文件映射对象的句柄,如果文件映射对象已经存在则返回原有映射对象的句柄,GetLastError返回ERROR_ALREADY_EXISTS。函数执行失败返回Null。
二、FlushViewOfFile 把文件映射视图中的修改的内容或全部写回到磁盘文件中
BOOL FlushViewOfFile(
LPCVOID lpBaseAddress, // 修改内容的起始地址
DWORD dwNumberOfBytesToFlush // 修改的字节数目
);
函数执行成功返回非零。
三、MapViewOfFile 在调用进程的地址空间映射一个文件视图
LPVOID MapViewOfFile(
HANDLE hFileMappingObject, // 已创建的文件映射对象句柄
DWORD dwDesiredAccess, // 访问模式
DWORD dwFileOffsetHigh, // 文件偏移的高32位
DWORD dwFileOffsetLow, // 文件偏移的低32位
DWORD dwNumberOfBytesToMap // 映射视图的大小
);
注意:
hFileMappingObject: 由CreateFileMapping 或 OpenFileMapping 返回的文件映射对象句柄。
dwDesiredAccess:映射视图的访问模式,与创建文件映射对象的保护模式flProtect有关,可以被设置为下列值:
FILE_MAP_WRITE:一个可读写属性的文件视图被创建,保护模式为PAGE_READWRITE
FILE_MAP_READ :一个只读属性的文件视图被创建,保护模式为PAGE_READWRITE 或 PAGE_READONLY
FILE_MAP_ALL_ACCESS:与FILE_MAP_WRITE模式相同
FILE_MAP_COPY:保护模式为PAGE_WRITECOPY时,得到一个视图文件,当你对视图文件写操作时,页面自动交换,并且你所做的修改不会损坏原始数据资料。
dwNumberOfBytesToMap:映射文件部分的大小,如果为0,则映射整个文件。
返回值:
如果成功返回返回映射视图的起始地址,如果失败返回NULL。
四、MapViewOfFileEx 在调用进程的地址空间映射一个文件视图,并且允许调用进程为映射视图指定特殊的内存地址 
LPVOID MapViewOfFileEx(
HANDLE hFileMappingObject, // 文件映射对象的句柄
DWORD dwDesiredAccess, // 访问模式
DWORD dwFileOffsetHigh, // 文件偏移的高32位
DWORD dwFileOffsetLow, // 文件偏移的低32位
DWORD dwNumberOfBytesToMap, // 映射视图的大小
LPVOID lpBaseAddress // 指定映射视图的其实内存地址
);
注意:
与MapViewOfFile用法相同,但是如果指定的内存地址空间大小不够,则函数执行失败。
五、OpenFileMapping 打开一个已命名的文件映射对象
HANDLE OpenFileMapping(
DWORD dwDesiredAccess, // 访问模式
BOOL bInheritHandle, // 继承标志
LPCTSTR lpName // 文件映射对象名指针
);
注意:
dwDesiredAccess:访问模式与MapViewOfFile中的访问模式相同。
bInheritHandle:继承标志,是否可以被一个新的进程继承使用,如果为TRUE,就可以被一个新进程继承句柄。
返回值:
成功返回一个已命名的文件映射对象,失败返回NULL。
六、UnmapViewOfFile 删除文件的映射视图
BOOL UnmapViewOfFile(
LPCVOID lpBaseAddress // 映射视图起始地址
);
注意:
lpBaseAddress:映射视图起始地址,由 MapViewOfFile 函数 MapViewOfFileEx产生。
返回值:
如果调用成功返回非零,并且所有指定地址内的脏页面会被写入硬盘。调用失败返回零。

 

还有什么函数的及其参数不懂的,自己去MSDN查下很详细的。

 

from:http://blog.renren.com/share/264265713/6836583299

你可能感兴趣的:(File,null,System,Access,attributes,磁盘)