MapViewOfFile chunked加载文件

时间:2014-12-14 18:53:46

标签: winapi memory-mapped-files

我想将文件映射到内存,块大小等于系统粒度。第一个块读取没有错误,所有其他块都因错误5(ERROR_ACCESS_DENIED)而失败。我尝试使用管理员权限运行程序。

我的代码:

#include <windows.h>
#include <stdio.h>

int main() {
        HANDLE hFile = CreateFile(      TEXT("db.txt"),
                                                                GENERIC_READ,
                                                                FILE_SHARE_READ,
                                                                NULL,
                                                                OPEN_EXISTING,
                                                                FILE_ATTRIBUTE_NORMAL,
                                                                NULL);
        if (hFile == INVALID_HANDLE_VALUE) {
                printf("[ERROR] File opening error %d\n", GetLastError());
                return 1;
        }

        printf("[DONE] File opened successfully.\n");

        HANDLE hMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
        if (hMap == NULL) {
                printf("[ERROR] Create mapping error %d\n", GetLastError());
                return 2;              
        }

        printf("[DONE] Create mapping successfully.\n");

        LARGE_INTEGER file_size = { };
        if (!GetFileSizeEx(hFile, &file_size)) {
                printf("[ERROR] Getiing filesize error %d\n", GetLastError());
                return 3;
        }

        printf("[DONE] Getting file size.\n");

        SYSTEM_INFO info = { };
        GetSystemInfo(&info);
        printf("[DONE] Getting system memory granularity %d.\n", info.dwAllocationGranularity);

        DWORD offset = 0;
        int size = 0;
        do {
                char* ENTRY = (char*)MapViewOfFile(hMap, FILE_MAP_READ, HIWORD(offset), LOWORD(offset), info.dwAllocationGranularity);
                if (ENTRY == NULL) {
                        printf("[ERROR] Map entry error %d\n", GetLastError());
                } else {
                        printf("[DONE] MAPPING PART WITH OFFSET %d\n", offset);
                        //printf("%s\n", ENTRY);
                }

                if (offset +  info.dwAllocationGranularity < file_size.QuadPart) {
                        offset += info.dwAllocationGranularity;
                } else {
                        offset = file_size.QuadPart;
                }
                //offset += size;      
                UnmapViewOfFile(ENTRY);
        } while (offset < file_size.QuadPart);




        CloseHandle(hMap);                             
        CloseHandle(hFile);
        system("pause");
        return 0;      
}

我如何解决?

1 个答案:

答案 0 :(得分:0)

您在HIWORD的调用中使用LOWORDMapViewOfFile作为偏移量,但这些只取32位值并将其拆分为两个16位的一半 - 你想要的是64位值分成两个32位的一半。

相反,您需要HIDWORDLODWORD,它们在<intsafe.h>中定义:

#define LODWORD(_qw)    ((DWORD)(_qw))
#define HIDWORD(_qw)    ((DWORD)(((_qw) >> 32) & 0xffffffff))

像这样:

char* ENTRY = (char*)MapViewOfFile(hMap, FILE_MAP_READ, HIDWORD(offset), LODWORD(offset), info.dwAllocationGranularity);

即使您的offset变量为32位,您也需要这样做(在这种情况下,HIDWORD只返回0,并且offset的完整值将作为低阶DWORD)。