MapViewOfFile читать из заданной позиции - PullRequest
0 голосов
/ 11 апреля 2020

Мне нужно прочитать большой файл по частям в ограниченный буфер. Мой код работает, но всегда читает с самого начала. Я думаю, что мне нужно как-то использовать dwFileOffsetHigh и dwFileOffsetLow, но я не могу понять, как. Mapper_Winapi_Uptr - это unique_ptr с пользовательским удалителем, при необходимости я могу выложить его код. Система: 64-битная Win10.

const std::vector<BYTE>& ReadFile(size_t pos) {

    memory = Mapper_Winapi_Uptr{ static_cast<BYTE*>(MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, bufferSize)) };
    std::memcpy(&data[0], memory.get(), bufferSize);
    return data;
}

1 Ответ

1 голос
/ 11 апреля 2020

Вы отображаете представление со смещением файла 0, игнорируя параметр pos, который предположительно является желаемым смещением файла.

MapViewOfFile() принимает 64-битное смещение в качестве входных данных, разбитое на 32-битные низкие и высокие значения , size_t может быть 32-битным или 64-битным типом, в зависимости от компилятора и платформы. Сначала вы можете поместить желаемое смещение в ULARGE_INTEGER, что даст вам низкие и высокие значения, которые вы можете затем присвоить MapViewOfFile().

Обратите внимание, что смещение файла, которое вы задаете для MapViewOfFile(), должно быть кратность гранулярности системы распределения. См. Создание представления в файле на MSDN для получения подробной информации о том, как с этим справиться.

Попробуйте что-то вроде этого:

SYSTEM_INFO SysInfo;
GetSystemInfo(&SysInfo);
DWORD SysGran = SysInfo.dwAllocationGranularity;
... 
const std::vector<BYTE>& ReadFile(size_t pos)
{
    size_t MapViewStart = (pos / SysGran) * SysGran;
    DWORD MapViewSize = (pos % SysGran) + bufferSize;
    DWORD ViewDelta = pos - MapViewStart;

    ULARGE_INTEGER ulOffset;
    ulOffset.QuadPart = MapViewStart;
    memory = Mapper_Winapi_Uptr{ static_cast<BYTE*>(MapViewOfFile(mapping, FILE_MAP_READ, ulOffset.HighPart, ulOffset.LowPart, bufferSize)) };
    if (!memory.get()) {
        // error handling ...
    }

    std::memcpy(&data[0], &(memory.get())[ViewDelta], bufferSize);
    return data;
}
...