Щоб відобразити файл в пам’ять на winapi, а також питання на - перевірку знань із зірочкою, записки

Відображенням файлу в пам'ять ми з вами користувалися в нотатках про OpenGL, присвячених роботі з моделями і текстурами. але не розглядали детально, як саме це працює. І хоча я майже впевнений, що багато Новомосковсктелі цього блогу вже знайомі з відображенням файлів в пам'ять, я все ж вважав необхідному написати відповідні замітки для тих Новомосковсктелей, кому даний механізм не знайомий. Сьогодні ми розглянемо, як все це працює під Windows.

Заведемо таку структуру, що зберігає хендл файлу, хендл відображення, розмір файлу, а також покажчик на ділянку пам'яті з відображенням:

struct FileMapping # 123;
HANDLE hFile;
HANDLE hMapping;
size_t fsize;
unsigned char * dataPtr;
# 125; ;

Розглянемо читання з файлу з використанням відображення.

HANDLE hFile = CreateFile # 40; fname, GENERIC_READ, 0. nullptr, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, nullptr # 41; ;
if # 40; hFile == INVALID_HANDLE_VALUE # 41; # 123;
std. cerr <<"fileMappingCreate - CreateFile failed, fname = "
< return nullptr;
# 125;

З процедурою CreateFile ми вже знайомі по замітці Вчимося працювати з файлами через Windows API. тому рухаємося далі.

Отримуємо розмір файлу:

DWORD dwFileSize = GetFileSize # 40; hFile, nullptr # 41; ;
if # 40; dwFileSize == INVALID_FILE_SIZE # 41; # 123;
std. cerr <<"fileMappingCreate - GetFileSize failed, fname = "
< CloseHandle # 40; hFile # 41; ;
return nullptr;
# 125;

Другим аргументом процедура GetFileSize отримує покажчик на DWORD для запису старшої частини розміру файлу. Передавши в якості цього аргументу nullptr, ми обмежили розмір файлу, який може повернуться. Якщо розмір файлу буде 4 Гб або більше, процедура поверне помилку.

HANDLE hMapping = CreateFileMapping # 40; hFile, nullptr, PAGE_READONLY, 0. 0,
nullptr # 41; ;
if # 40; hMapping == nullptr # 41; # 123;
std. cerr <<"fileMappingCreate - CreateFileMapping failed, fname = "
< CloseHandle # 40; hFile # 41; ;
return nullptr;
# 125;

Зауважте, що hMapping перевіряється на рівність nullptr. Це не баг - згідно MSDN, в разі помилки CreateFileMapping дійсно повертає порожній покажчик, а не INVALID_HANDLE_VALUE, як можна було б очікувати. Така неконсістентность, на жаль, зустрічається час від часу в WinAPI. Ми вже зустрічалися з цією проблемою, вивчаючи роботу з реєстром.

Нарешті, отримуємо покажчик на ділянку пам'яті з відображенням, використовуючи процедуру MapViewOfFile:

unsigned char * dataPtr = # 40; unsigned char * # 41; MapViewOfFile # 40; hMapping,
FILE_MAP_READ,
0,
0,
dwFileSize # 41; ;
if # 40; dataPtr == nullptr # 41; # 123;
std. cerr <<"fileMappingCreate - MapViewOfFile failed, fname = "
< CloseHandle # 40; hMapping # 41; ;
CloseHandle # 40; hFile # 41; ;
return nullptr;
# 125;

Потім заповнюємо структуру FileMapping і повертаємо покажчик на неї в якості результату:

FileMapping * mapping = # 40; FileMapping * # 41; malloc # 40; sizeof # 40; FileMapping # 41; # 41; ;
if # 40; mapping == nullptr # 41; # 123;
std. cerr <<"fileMappingCreate - malloc failed, fname = "
< UnmapViewOfFile # 40; dataPtr # 41; ;
CloseHandle # 40; hMapping # 41; ;
CloseHandle # 40; hFile # 41; ;
return nullptr;
# 125;

mapping -> hFile = hFile;
mapping -> hMapping = hMapping;
mapping -> dataPtr = dataPtr;
mapping -> fsize = # 40; size_t # 41; dwFileSize;

Коли відображення стає непотрібним, не забуваємо його закрити:

UnmapViewOfFile # 40; mapping -> dataPtr # 41; ;
CloseHandle # 40; mapping -> hMapping # 41; ;
CloseHandle # 40; mapping -> hFile # 41; ;
free # 40; mapping # 41; ;

Як бачите, все гранично просто. Вихідні тексти до цієї замітці ви знайдете тут.

Сподобався пост? Поділися з іншими:

(Необхідно включити JS)