FreeBASIC в России

   

 Главная   Исходники   Русскоязычный форум   Полезные файлы   Пользователи   Поиск

 

 FB Wiki   Уроки   Скачать FreeBASIC   Проекты   Ссылки   Загрузить   Каталог ссылок

 
 

 Замечания и предложения по работе сайта оставляйте здесь.

Сейчас на сайте:

Вы вошли как: Guest   Регистрация   

Логин:     Пароль:     

Создай бесплатно WebMoney кошелёк на своём мобильном всего за 5 минут

 

Делаем dll своими руками

Хэндл окна

Графические средства языка

Точка пересечения отрезков

Окна без рамки

Физика поведения ядра

Win32 API Введение

►Урок 1 Win32 API

►Урок 2 Win32 API

►Урок 3 Win32 API

►Урок 4 Win32 API

►Урок 5 Win32 API

►Урок 6 Win32 API

►Урок 7 Win32 API

►Урок 8 Win32 API

►Урок 9 Win32 API

►Урок 10 Win32 API

►Урок 11 Win32 API

►Урок 12 Win32 API

►Урок 13 Win32 API

►Урок 14 Win32 API

►Урок 15 Win32 API

►Урок 16 Win32 API

►Урок 17 Win32 API

►Урок 18 Win32 API

►Урок 19 Win32 API

►Урок 20 Win32 API

►Урок 21 Win32 API

►Урок 22 Win32 API

►Урок 23 Win32 API

►Урок 24 Win32 API

Ассоциация файлов

Определить OS

Выводит имя компьютера

 

 

 

Win32 API. Урок 13. Memory Mapped файлы.

Опытом поделился и оптимизировал под FreeBASIC:   15.01.2011

 

 

Реклама:

you tube;Заказать саморегулируемые организации в проектировании на сайте.

 

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

Теория:

Если вы хорошо изучили пример из прошлого туториала, вы увидите, что у него есть серьезный недостаток: что, если файл, который вы хотите прочитать больше, чем зарезервированный блок памяти? или если строка, которую вы хотите найти будет обрезана посередине, потому что кончился блок памяти? Традиционный ответ
на первый вопрос - это то, что вам нужно последовательно читать данные из файла, пока он не кончится. Ответом на второй вопрос является то, что вы должны обрабатывать подобную возможность. Это называется проблемой пограничного значения. Она представляет собой головную большую для программистов и вызывает неисчислимое количество багов.

Было бы неплохо, если бы мы могли зарезервировать очень большой блок памяти, достаточный для того, чтобы сохранить весь файл, но наша программа стала бы очень прожорливой в плане ресурсов. File mapping - это спасение. Используя его, вы можете считать весь файл уже загруженным в память и использовать указатель
на память, чтобы читать или писать данные в файл. Очень просто. Нет нужды использовать API памяти и файловые API одновременно, в FM это одно и то же. FM
также используется для обмена данными между процессами. При использовании FM таким образом, реально не используется никакой файл. Это больше похоже на
блок памяти, который могут видеть все процессы. Но обмен данными между процессами - весьма деликатный предмет. Вы должны будете обеспечить синхронизацию между процессами и ветвями, иначе ваше приложение очень скоро повиснет.

Мы не будем касаться того, как использовать FM для создания общего региона памяти в этом туториале. Мы сконцентрируемся на том, как использовать FM для "загрузки" файла в память. Фактически, PE-загрузчик использует FM для загрузки исполняемых файлов в память. Это очень удобно, так как только необходимые
порции файла будут считываться с диска. Под Win32 вам следует использовать FM так часто, как это возможно.

Правда, существует несколько ограничений при использовании FM. Как только вы создали такой файл, его размер не может изменяться до закрытия сессии. Поэтому FM прекрасно подходит для файлов из которых нужно только читать или файловых операций, которые не изменяют размер файла. Это не значит, что вы не можете использовать FM, если хотите увеличить размер файла. Вы можете установить новый размер и создать MMF нового размера и файл увеличится до этого размера. Это просто неудобно, вот и все.
Достаточно объяснений. Давайте перейдем к реализации FM. Для того, чтобы его использовать, должны быть выполнены следующие шаги.

• Вызов CreateFile для открытия файла.
• Вызов CreateFileMapping, которой передается хэндл файла, возвращенный CreateFile. Эта функция создает FM-объект из файла, созданного CreateFile'ом.
• Вызов MapViewOfFile, чтобы загрузить выбранный файловый регион или весь файл в память. Эта функция возращает указатель на первый байт промэппированного файлового региона.
• Используйте указатель, чтобы писать или читать из файла.
• Вызовите UnmapViewOfFile, чтобы выгрузить файл.
• Вызов CloseHandle, передав ему хэндл промэппированного файла в качестве одного из параметра, чтобы закрыть его.
• Вызов CloseHandle снова, передав ему в этот раз хэндл файла, возвращенный CreateFile, чтобы закрыть сам файл.


Пример:

Программа, листинг которой приведен ниже, позволит вам открыть файл с помощью окна открытия файла. Она откроет файл, используя FM, если это удастся, заголовок окна изменится на имя открытого файла. Вы можете сохранить файл под другим именем, выбрав пункт меню File/Save. Программа скопирует все содержимое открытого файла в новый файл. Учтите, что вы не должны вызывать GlobalAlloc для резервирования блока памяти в этой программе.

файл mmf.bas

Скопировать данный код в буфер обмена

файл mmf.bi

Скопировать данный код в буфер обмена

файл mmf.rc

Скопировать данный код в буфер обмена

Анализ:

hFileRead = CreateFile _
(@buffer, _
GENERIC_READ, _
0, _ ' доступ другим процессам
NULL, _ ' атрибуты безопасности
OPEN_EXISTING, _
FILE_ATTRIBUTE_ARCHIVE, _
NULL)

Когда пользователь выбирает файл в окне открытия файла, мы вызываем CreateFile, чтобы открыть его. Заметьте, что мы указываем GENERIC_READ, чтобы открыть этот файл в режиме read-only, потому что мы не хотим, чтобы какие-либо другие процессы изменяли файл во время нашей работы с ним.

hMapFile = CreateFileMapping _
(hFileRead, _
NULL, _
PAGE_READONLY, _
0,0,NULL)

Затем мы вызываем CreateFileMapping, чтобы создать MMF из открытого файла. CreateFileMapping имеет следующий синтаксис:

function CreateFileMapping _
(byval hFile as HANDLE, _
byval lpFileMappingAttributes as LPSECURITY_ATTRIBUTES, _
byval flProtect as DWORD, _
byval dwMaximumSizeHigh as DWORD, _
byval dwMaximumSizeLow as DWORD, _
byval lpName as LPCSTR) as HANDLE

Вам следует знать, что CreateFileMapping не обязана мэппировать весь файл в память. Вы можете промэппировать только часть файла. размер мэппируемого файла вы задаете параметрами dwMaximumSizeHigh и dwMaximumSizeLow. Если вы зададите размер больше, чем его действительный размер, файл будет увеличен до нового размера. Если вы хотите, чтобы MMF был такого же размера, как и исходный файл, сделайте оба параметра равными нулю.

Вы можете использовать NULL в lpFileMappingAttributes, чтобы Windows создали MMF со значениями безопасности по умолчанию.
flProtect определяет желаемую защиту для MMF. В нашем примере, мы используем PAGE_READONLY, чтобы разрешить только операции чтения над MMF. Заметьте, что
этот атрибут не должен входить в противоречие с атрибутами, указанными в CreateFile, иначе CreateFileMapping возвратит ошибку.

lpName указывает на имя MMF. Если вы хотите разделять этот файл с другими процессами, вы должны присвоить ему имя. Но в нашем примере другие процессы не будут его использовать, поэтому мы игнорируем этот параметр.

SetWindowText _
(hWnd, _
(@buffer + ofn.nFileOffset))

Если CreateFileMapping выполнилась успешно, мы изменяем название окна на имя открытого файла. Имя файла с полным путем сохраняется в буфере, мы же хотим отобразить только собственно имя файла, поэтому мы должны добавить значение параметра nFileOffset структуры OPENFILENAME к адресу буфера.

EnableMenuItem _
(hMenu, _
IDM_OPEN, _
MF_GRAYED)
EnableMenuItem _
(hMenu, _
IDM_SAVE, _
MF_ENABLED)

В качестве предосторожности, мы не хотим чтобы пользователь мог открыть несколько файлов за раз, поэтому делаем пункт меню Open недоступным для выбора и делаем доступным пункт Save.
EnableMenuItem используется для изменения атрибутов пункта меню.
После этого, мы ждем, пока пользователь выберет File/Save или закроет программу.

case WM_DESTROY ' если пользователь закрывает окно
if hMapFile <> 0 then ' если map файл открыт
CloseMapFile() ' закроем map файл
end if
PostQuitMessage(0) ' выходим из программы

В выше приведенном коде, когда процедура окна получает сообщение WM_DESTROY, она сначала проверяет значение hMapFile - равно ли нулю или нет. Если оно не равно нулю, она вызывает функцию CloseMapFile, которая содержит следующий код:

sub CloseMapFile()
CloseHandle _ ' закроем хэндл
(hMapFile) ' map файла
hMapFile = 0 ' пишем в хэндл 0

CloseHandle _ ' закроем хэндл
(hFileRead) ' исходного файлла
end sub

CloseMapFile закрывает MMF и сам файл, так что наша программа не оставляет за собой следов при выходе из Windows. Если пользователь выберет сохранение информации в другой файл, программа покажет ему окно сохранения файла. После он сможет напечатать имя нового файла, который и будет создан функцией CreateFile.

pMemory = MapViewOfFile _
(hMapFile, _
FILE_MAP_READ, _
0,0,0)

Сразу же после создания выходного файла, мы вызываем MapViewOfFile, чтобы промэппировать желаемую порцию MMF в память. Эта функция имеет следующий синтаксис:

function MapViewOfFile _
(byval hFileMappingObject as HANDLE, _
byval dwDesiredAccess as DWORD, _
byval dwFileOffsetHigh as DWORD, _
byval dwFileOffsetLow as DWORD, _
byval dwNumberOfBytesToMap as DWORD) as PVOID

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

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

dwNumberOfBytesToMap задает количество байтов, которое нужно промэппировать в память. Чтобы сделать это со всем файлом, передайте ноль MapViewOfFile.

После вызова MapViewOfFile, желаемое количество загружается в память. Вы получите указатель на блок памяти, который содержит данные из файла.

SizeFile = GetFileSize _
(hFileRead, _
NULL)

Теперь узнаем, какого размера наш файл. размер файла возвращается в SizeFile.\ Если файл больше, чем 4 GB, то верхнее двойное слово размера файла сохраняется в FileSizeHighWord. Так как мы не ожидаем встретить таких больших файлов, мы можем проигнорировать это.

WriteFile _
(hFileWrite, _
pMemory, _
SizeFile, _
@SizeWritten, _
NULL)

Запишем данные в выходной файл.

UnmapViewOfFile (pMemory)

Когда мы заканчиваем со входным файлом, вызываем UnmapViewOfFile.

CloseMapFile()
CloseHandle(hFileWrite)

И закрываем все файлы.

SetWindowText _ ' установим в окно текст
(hWnd, _
@AppName)

Восстанавливаем оригинальное название окна.

EnableMenuItem _
(hMenu, _
IDM_OPEN, _
MF_ENABLED)
EnableMenuItem _
(hMenu, _
IDM_SAVE, _
MF_GRAYED)

разрешаем доступ к пункту меню Oрen и запрещаем к Save As.

[C] Iczelion, пер. Aquila.

 

 

Прокомментировать

Ваше имя:  

Ваш e-mail:  

Сообщение:



Введите код: 

 

 

   Спасибо можно сказать, посетив любую ссылку:

 

 

© 2010-2012

DEPOzit (Попов Денис Владимирович)

WebMoney кошелёк: WMID#302963000004

ICQ:279786014 или R549103331586   Z116647355686