2017-02-23 40 views
0

У меня есть очень большой файл, который я бы хотел использовать CreateFileMapping и MapViewOfFile для извлечения из него 10 байтов текста на основе заданного номера идентификатора. Так вот что я тщетно,случайным образом читает файл с mapviewoffile

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» и an identifier = 122 тогда моя программа должна прочитать 10 байтов текста, начиная с 1220-го байта в файл и вернуть их для дальнейшей обработки.

Я написал этот код исключительно на основе нескольких ресурсов, которые я нашел на SO и до сих пор у меня не было ни одного тщательного идею о том, что на земле

_In_  DWORD dwFileOffsetHigh, 
_In_  DWORD dwFileOffsetLow, 

в этих двух функций на самом деле означает сделать. И я думаю, что мои параметры передавались в них, как в приведенных выше программах, неверны.

+1

Зачем использовать сопоставление памяти для этого, когда вы можете открыть файл и искать нужный вам счет? – molbdnilo

+0

64-разрядное число разделено на два 32-битных значения, ** высокий ** est 32 бит и ** низкий ** est 32 бит. –

+0

Но зачем они и как их использовать в этом случае? –

ответ

0

Ваши расчеты выглядят правильно, но вы забыли о том, что вид на 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; 
} 

(.. Я не проверял этот код, так что может быть несколько опечаток Но это должно дать вам основную идею)

Если файл может быть больше 4 ГБ, вам нужно будет выполнить 64-разрядный расчет.

Обратите внимание, что (в зависимости от размера файла и биты вашего приложения) было бы разумнее поддерживать постоянный отображаемый вид всего файла, чем создавать новое сопоставление каждый раз, когда вам нужно читать 10 байт. По крайней мере, рекомендуется поддерживать постоянный объект сопоставления, даже если вы хотите переназначить представление каждый раз; вы обнаружите, что это значительно снижает накладные расходы.

+0

Спасибо @ Харри Джонстон. Программа выводится правильно. ~)) –

1
  1. Здесь мало оснований использовать сопоставление файлов. Открывать, искать и читать. Сопоставление файлов не волшебным образом быстрее.

  2. dwFileOffsetHigh и dwFileOffsetLow объединяются с 64-битным смещением в файл, где начинается «Вид». Вы можете просмотреть несколько видов одного файла, начиная с разных смещений. Смещение должно быть кратным размеру страницы. Таким образом, вы не можете начинать, когда хотите

  3. dwFileMapSize (высокий и низкий - это 64-разрядное значение) должен быть максимальным размером файла, доступного при сопоставлении.

  4. Сбой диска и удаление диска могут привести к (системному) исключению. Вам нужно будет справиться с этим, если вы не хотите, чтобы ваша программа рушилась в этой ситуации.

  5. Обратите внимание, что ваша спецификация смещения позволяет сегменту размером 10 байтов пересекать границу страницы. Вы должны убедиться, что ваш взгляд тянется две страницы

+0

@ Харри Джонстен: спасибо за указание, исправлено. – peterchen