Практические примеры - на WinAPI, и на MFC
Теория: Файл, спроецированный на память - это механизм Win32 API, позволяющий любой открытый файл рассматривать как блок пямяти с произвольным доступом (все записи и чтения байта по адресу, лежащему в пределах такого блока, приводят к изменению соотв. байта в файле). Это может быть очень удобно, когда необходимо работать с файлами очень большого объема: вместо того, чтобы читать всё содержимое файла в память (или искать нужный фрагмент функцией Seek), можно спроецировать файл на память и сразу прочитать или модифицировать нужный фрагмент памяти. Windows подгружает спроецированный файл постранично, по мере обращения к тем или иным адресам памяти; всё делается автоматически, на уровне механизма виртуальной памяти Win32, что избавляет от необходимости вручную следить за подгрузкой из файла или записью в файл ненужных участков памяти.
Пример на MFC: Чтобы упростить себе жизнь, создадим простой класс на основе CFile (класс-предок будет заниматься открытием и закрытием файлов; нам же останется только реализовать в нашем классе пару функций для проецирования файла):
Код | class CMemoryMappedFile: public CFile { protected: HANDLE m_hMapping; // хэндл объекта "проекция файла" void *m_bufMapping; // стартовый адрес проекции
public: // набор конструкторов CMemoryMappedFile() {m_hMapping=NULL;} CMemoryMappedFile(char *strFileName, UINT openFlags): CFile(strFileName, openFlags) {m_hMapping=NULL;} ~CMemoryMappedFile() {if(m_hMapping) ReleaseMemoryMapping();}
public: // пара функций "спроецировать" / "освободить проекцию" void *GetMemoryMapping(bool bReadOnly=false); void ReleaseMemoryMapping(); };
// функция проецирует файл на память (файл должен быть уже открыт) // и возвращает стартовый адрес блока памяти void *CMemoryMappedFile::[b]GetMemoryMapping(bool bReadOnly)[/b] { if(!m_hFile || m_hMapping) return NULL; m_hMapping = CreateFileMapping((void*)m_hFile, 0, bReadOnly?PAGE_READONLY:PAGE_READWRITE, 0, 0, 0); if(!m_hMapping) return NULL; m_bufMapping = MapViewOfFile(m_hMapping, FILE_MAP_READ|(bReadOnly?0:FILE_MAP_WRITE), 0, 0, 0); if(!m_bufMapping) CloseHandle(m_hMapping); return m_bufMapping; }
// освобождение проекции void CMemoryMappedFile::[b]ReleaseMemoryMapping[/b]() { if(!m_hMapping) return; UnmapViewOfFile(m_bufMapping); CloseHandle(m_hMapping); m_hMapping = NULL; }
// ===============================================
// пример - создадим текстовый файл на диске С: и запишем // в него строку текста, затем заменим третий символ на "Z": void DemoFileMapping() { CMemoryMappedFile file("c:\\1.txt", CFile::modeCreate|CFile::modeReadWrite); char *str = "ABCDEFG"; file.Write(str, strlen(str));
char *buf = (char*)file.GetMemoryMapping(); buf[2] = 'Z'; file.ReleaseMemoryMapping(); } |
Пример на "чистом" WinAPI:
Код | // пример - создадим текстовый файл на диске С: и запишем // в него строку текста, затем заменим третий символ на "Z": void DemoFileMapping() { HANDLE hFile = CreateFile ( "c:\\1.txt", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); DWORD d; char *str = "ABCDEFG"; WriteFile(hFile, str, strlen(str), &d, 0); HANDLE mapping = CreateFileMapping(hFile, 0, PAGE_READWRITE, 0, 0, 0); if(mapping) { char *buf = (char *)MapViewOfFile(mapping, FILE_MAP_ALL_ACCESS, 0, 0, 0); if(buf) { buf[2] = 'Z'; UnmapViewOfFile(buf); } CloseHandle(mapping); } CloseHandle(hFile); } |
|