C++ 使用mapviewoffile随机读取文件

C++ 使用mapviewoffile随机读取文件,c++,winapi,C++,Winapi,我有一个非常大的文件,我想使用CreateFileMapping和MapViewOfFile根据给定的标识符编号从中提取10字节的文本。这就是我徒劳的尝试 char* Read(char*pFilename, int id) { HANDLE hFile = ::CreateFile(pFilename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); GetSys

我有一个非常大的文件,我想使用CreateFileMapping和MapViewOfFile根据给定的标识符编号从中提取10字节的文本。这就是我徒劳的尝试

char* Read(char*pFilename, int id)
{
    HANDLE hFile = ::CreateFile(pFilename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    GetSystemInfo(&sysInfo);
    DWORD dwSysGran = sysInfo.dwAllocationGranularity;
    DWORD dwFileMapStart = ((id*10/ dwSysGran)*dwSysGran);
    DWORD dwMapViewSize = (id*10 % dwSysGran) + 10;
    DWORD dwFileMapSize = id*10 + 10;
    char data[10];
    HANDLE hMap = ::CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, dwFileMapSize, NULL);
    if (hMap != NULL)
    {
        char *rawBuffer = (char*)MapViewOfFile(hMap, FILE_MAP_READ, 0, dwFileMapStart, dwMapViewSize);
        memcpy(&data[0], rawBuffer, 10);
        UnmapViewOfFile(rawBuffer);
    }
//...
    return data;
}
例如,如果用户输入一个名为“characterWeaponData.ucc”的文件,并且
标识符=122
然后,我的程序需要从上的文件中的第1220个字节开始读取10个字节的文本,并返回它们进行进一步处理

我写这段代码完全是基于我在SO上找到的几个资源,直到现在我还没有一个完整的想法到底是什么

_In_     DWORD  dwFileOffsetHigh,
 _In_     DWORD  dwFileOffsetLow,
在这两个功能中真正意味着做什么。我猜我在上面的程序中输入的参数是不正确的

  • 这里没有什么理由使用文件映射。打开,寻找,阅读。文件映射并没有神奇地更快

  • dwFileOffsetHigh
    dwFileOffsetLow
    组合成一个64位偏移量到“视图”开始的文件中。一个文件映射可以有多个视图,从不同的偏移开始。偏移量必须是页面大小的倍数。所以你不能让它从你想要的任何地方开始

  • dwFileMapSize
    (高和低是64位值)必须是映射中可用文件的最大大小

  • 磁盘故障和磁盘移除可能会导致(系统)异常。如果你不想让你的程序在这种情况下崩溃,你需要处理这个问题

  • 请注意,偏移量规范允许10字节的段跨越页面边界。您必须确保视图延伸两页


  • 您的计算看起来是正确的,但您忘记了
    rawBuffer
    处的视图指向偏移量
    dwFileMapStart
    ,而不是
    id*10

    我想试试这样的东西:

    char* Read(char*pFilename, int id)
    {
        HANDLE hFile = ::CreateFile(pFilename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
        GetSystemInfo(&sysInfo);
        DWORD dwSysGran = sysInfo.dwAllocationGranularity;
        DWORD dwSize = 10;
        DWORD dwOffset = id*dwSize;
        DWORD dwFileMapStart = ((dwOffset/dwSysGran)*dwSysGran);
        DWORD dwMapViewSize = dwOffset + dwSize - dwFileMapStart;
        char data[10];
        HANDLE hMap = ::CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
        if (hMap != NULL)
        {
            char *rawBuffer = (char*)MapViewOfFile(hMap, FILE_MAP_READ, 0, dwFileMapStart, dwMapViewSize);
            memcpy(&data[0], rawBuffer + (dwOffset - dwFileMapStart), dwSize);
            UnmapViewOfFile(rawBuffer);
        }
    //...
        return data;
    }
    
    (我还没有测试过这段代码,所以可能会有一些拼写错误。但它应该能告诉你基本的想法。)

    如果文件可能大于4GB,则需要进行64位计算


    请注意(取决于文件大小和应用程序的位数),维护整个文件的永久映射视图可能比每次需要读取10个字节时创建新映射更有意义。至少要考虑维护一个永久映射对象,即使您希望每次重新映射视图;您会发现它大大减少了开销。

    当您可以打开文件并查找到感兴趣的偏移量时,为什么要使用内存映射呢?64位数字拆分为两个32位值,最高32位和最低32位。但它们是干什么用的?在这种情况下如何使用它们?@molbdnilo,因为我现在只喜欢使用winapi。您可以使用Win32 API读取文件。谢谢@Harry Johnston。程序现在输出正确。~)