Форум: "WinAPI";
Текущий архив: 2004.10.10;
Скачать: [xml.tar.bz2];
ВнизMMF Найти похожие ветки
← →
Роман Снегирев (2004-08-30 09:57) [0]Доброго всем времени суток.
Может кто подкинут ссылочку на инфу по отображению файлов на в память (memory mapped files). Желательно с реализацией на Delphi.
← →
VMcL © (2004-08-30 10:07) [1]>>Роман Снегирев (30.08.04 09:57)
Здесь пример применения:
http://www.delphimaster.ru/articles/hooks/index.html
← →
Rouse_ © (2004-08-30 11:44) [2]////////////////////////////////////////////////////////////////////////////////
//
// Демо работы с Файлами отображенными в память процесса
// Автор: Александр (Rouse_) Багель
// © Fangorn Wizards Lab 1998 - 2003
// 23 мая 2003 17:06
// Закоментированные строки содержат пример передачи структуры
структуры
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
const
MMFID = "{D9CFD3BD-3E91-4748-B9F9-7A1825847DF7}";
type
{
PTestStructure = ^TTestStructure;
TTestStructure = packed record
A: Integer;
B: Boolean;
C: ShortString;
end;
}
TForm1 = class(TForm)
memSender: TMemo;
btnCreate: TButton;
memReceive: TMemo;
btnAdd: TButton;
btnClose: TButton;
btnOpen: TButton;
btnRead: TButton;
btnCloseOpen: TButton;
procedure btnAddClick(Sender: TObject);
private
TextAdded, // Два флага для
IsOpenFile: Boolean; // для управления состоянием кнопок
SendMMF, RecMMF: THandle;
SendData, RecData: PChar;
procedure ButtonState(const btnState: Integer);
function OpenSendMMF: Boolean;
function AddText: Boolean;
function CloseSend: Boolean;
function OpenRecMMF: Boolean;
function ReadText: Boolean;
function CloseRec: Boolean;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
// Управляем состоянием кнопок
// Кнопки становятся доступными в тот момент, когда текущая операция,
// содержащаяся в обработчике кнопки, возможна ...
// =============================================================================
procedure TForm1.ButtonState(const btnState: Integer);
begin
case btnState of
0:
begin
btnAdd.Enabled := True;
btnClose.Enabled := True;
btnOpen.Enabled := True;
end;
1:
begin
TextAdded := True;
btnRead.Enabled := IsOpenFile;
end;
2:
begin
TextAdded := False;
btnAdd.Enabled := False;
btnClose.Enabled := False;
btnOpen.Enabled := False;
btnRead.Enabled := False;
btnCloseOpen.Enabled := False;
end;
3:
begin
IsOpenFile := True;
btnCloseOpen.Enabled := True;
btnRead.Enabled := TextAdded;
end;
5:
begin
IsOpenFile := False;
btnRead.Enabled := False;
btnCloseOpen.Enabled := False;
end;
end;
end;
// Общий обработчик для всех кнопок ...
// =============================================================================
procedure TForm1.btnAddClick(Sender: TObject);
var
State: Boolean;
begin
State := False;
case TComponent(Sender).Tag of
0: State := OpenSendMMF;
1: State := AddText;
2: State := CloseSend;
3: State := OpenRecMMF;
4: State := ReadText;
5: State := CloseRec;
end;
if State then
ButtonState(TComponent(Sender).Tag);
end;
// Создаем Memory Mapped File ...
// =============================================================================
function TForm1.OpenSendMMF: Boolean;
begin
SendMMF := CreateFileMapping($FFFFFFFF, nil, PAGE_READWRITE, 0, 4096,
PChar(MMFID));
Result := SendMMF <> 0;
end;
// Добавляем в файл текст ...
// (передача структуры находится в закоментированных строках кода)
// =============================================================================
function TForm1.AddText: Boolean;
{var
F: TTestStructure;
Z: PTestStructure;}
begin
SendData := MapViewOfFile(SendMMF, FILE_MAP_WRITE, 0, 0, 0);
Result := SendData <> nil;
StrPCopy(SendData, memSender.Text);
{F.A := 123;
F.B := True;
F.C := "This is are test message";
Z := MapViewOfFile(SendMMF, FILE_MAP_WRITE, 0, 0, 0);
Result := Z <> nil;
Z^ := F;}
end;
// Разрушаем Memory Mapped File ...
// =============================================================================
function TForm1.CloseSend: Boolean;
begin
if btnCloseOpen.Enabled then CloseRec;
UnmapViewOfFile(SendData);
SendData := nil;
CloseHandle(SendMMF);
Result := True;
end;
// Открываем созданный ранее Memory Mapped File ...
// =============================================================================
function TForm1.OpenRecMMF: Boolean;
begin
RecMMF := OpenFileMapping(FILE_MAP_ALL_ACCESS, False, PChar(MMFID));
Result := RecMMF <> 0;
end;
// Читаем из него данные ...
// (прием структуры находится в закоментированных строках кода)
// =============================================================================
function TForm1.ReadText: Boolean;
{var
F: TTestStructure;
Z: PTestStructure;}
begin
RecData := MapViewOfFile(RecMMF, FILE_MAP_ALL_ACCESS, 0, 0, 0);
Result := RecData <> nil;
memReceive.Text := RecData;
{Z := MapViewOfFile(SendMMF, FILE_MAP_ALL_ACCESS, 0, 0, 0);
F := Z^;
Result := Z <> nil;
Caption := F.C;}
end;
// Закрываем (не разрушаем) Memory Mapped File ...
// =============================================================================
function TForm1.CloseRec: Boolean;
begin
UnmapViewOfFile(RecData);
RecData := nil;
CloseHandle(RecMMF);
Result := True;
end;
end.
← →
Роман Снегирев (2004-08-30 14:51) [3]Не совсем то, что нужно. Мне надо открыть файл с диска, типа замэпить его в память и читать оттуда данные.
← →
VMcL © (2004-08-30 14:59) [4]>>Роман Снегирев (30.08.04 14:51) [3]
CreateFile(), потом CreateFileMapping(), потом MapViewOfFile(), потом читаешь файл посредством указателя, полученного от MapViewOfFile() (если нужно, в цикле повторяешь UnmapViewOfFile() + MapViewOfFile()), в конце: UnmapViewOfFile(), CloseHandle() для мэппинга + CloseHandle() для файла
← →
wicked © (2004-08-30 15:12) [5]например, так:
unit MMapStream;
interface
uses Windows, SysUtils, Classes;
{$WEAKPACKAGEUNIT ON}
const
def_Granularity = (512 * 1024);
type
TMemoryMapStream = class(TCustomMemoryStream)
protected
fRealSize: integer;
fGranularity: integer;
fFile: THandle;
fMemMap: THandle;
fReadOnly: boolean;
procedure SetSize(const NewSize: int64); overload; override;
procedure SetGranularity(value: integer); virtual;
procedure OpenMMap; virtual;
procedure CloseMMap; virtual;
procedure Map; virtual;
procedure UnMap; virtual;
procedure doPack(reopen: boolean); virtual;
procedure SetEOF(pos: integer); virtual;
public
constructor Create(const AFileName: string; RequestReadOnly: boolean = false; AGranularity: integer = def_Granularity);
destructor Destroy; override;
procedure Clear;
procedure SetSize(NewSize: integer); overload; override;
function Write(const Buffer; Count: longint): longint; override;
procedure LoadFromFile(const FileName: string); virtual;
procedure LoadFromStream(Stream: TStream); virtual;
procedure Pack; virtual;
property Granularity: integer read fGranularity write SetGranularity;
property ReadOnly: boolean read fReadOnly;
end;
implementation
const
min_size = 1024;
constructor TMemoryMapStream.Create(const AFileName: string; RequestReadOnly: boolean = false; AGranularity: integer = def_Granularity);
var filesize: integer;
begin
inherited Create;
SetPointer(nil, 0);
fRealSize:= 0;
SetGranularity(AGranularity);
fFile := 0;
fMemMap := 0;
fReadOnly := false;
try
if not RequestReadOnly then
fFile := CreateFile(
PChar(AFileName), // name
GENERIC_READ or GENERIC_WRITE, // desired access
FILE_SHARE_READ, // share mode (share read)
nil, // security attributes
OPEN_ALWAYS, // OPEN_EXISTING, // creation disposition
FILE_ATTRIBUTE_NORMAL or FILE_FLAG_RANDOM_ACCESS, // flags and attributes
0{nil}); // template file
if (fFile = INVALID_HANDLE_VALUE) or RequestReadOnly then begin
fFile := CreateFile(
PChar(AFileName), // name
GENERIC_READ, // desired access
FILE_SHARE_READ, // share mode (share read)
nil, // security attributes
OPEN_EXISTING, // creation disposition
FILE_ATTRIBUTE_NORMAL or FILE_FLAG_RANDOM_ACCESS, // flags and attributes
0{nil}); // template file
if fFile = INVALID_HANDLE_VALUE then raise Exception.Create("could not open the file " + AFileName);
fReadOnly := true;
end;
filesize := GetFileSize(fFile, nil);
if filesize = 0 then SetEOF(min_size);
OpenMMap;
except
CloseMMap;
if (fFile <> 0) and (fFile <> INVALID_HANDLE_VALUE) then CloseHandle(fFile);
raise;
end;
Seek(0, soFromBeginning);
end;
destructor TMemoryMapStream.Destroy;
begin
if fFile <> 0 then begin
doPack(false);
CloseHandle(fFile);
end;
end;
procedure TMemoryMapStream.OpenMMap;
begin
if fFile <> 0 then begin
if fReadOnly then fMemMap := CreateFileMapping(fFile, nil, PAGE_READONLY or SEC_COMMIT, 0, 0, nil)
else fMemMap := CreateFileMapping(fFile, nil, PAGE_READWRITE or SEC_COMMIT, 0, 0, nil);
if fMemMap = 0 then raise Exception.Create("could not create memory map of file");
Map;
end;
end;
procedure TMemoryMapStream.CloseMMap;
begin
if fMemMap <> 0 then begin
UnMap;
CloseHandle(fMemMap);
end;
end;
procedure TMemoryMapStream.Map;
var p: pointer;
filesize: integer;
begin
SetPointer(nil, 0);
if fReadOnly then
p := MapViewOfFile(fMemMap, FILE_MAP_READ, 0, 0, 0)
else
p := MapViewOfFile(fMemMap, FILE_MAP_ALL_ACCESS, 0, 0, 0);
if p = nil then raise Exception.Create("could not read file");
filesize := GetFileSize(fFile, nil);
fRealSize := filesize;
SetPointer(p, filesize);
Position := 0;
end;
procedure TMemoryMapStream.UnMap;
begin
if Memory <> nil then begin
if not fReadOnly then FlushViewOfFile(Memory, 0);
UnmapViewOfFile(Memory);
end;
end;
procedure TMemoryMapStream.doPack(reopen: boolean);
begin
CloseMMap;
try
SetEOF(Size);
finally
if reopen then OpenMMap;
end;
end;
procedure TMemoryMapStream.SetEOF(pos: integer);
begin
if fReadOnly then exit;
if SetFilePointer(fFile, pos, nil, FILE_BEGIN) = DWORD(-1) then // !!! INVALID_SET_FILE_POINTER
raise Exception.Create("could not resize file");
SetEndOfFile(fFile);
end;
//---------------------------------------------------------------------------
procedure TMemoryMapStream.SetSize(const NewSize: int64);
begin
SetSize(integer(NewSize));
end;
procedure TMemoryMapStream.SetGranularity(value: integer);
begin
if value = fGranularity then exit;
fGranularity := value;
if fGranularity < min_size then fGranularity := min_size;
end;
procedure TMemoryMapStream.Clear;
begin
SetSize(min_size);
doPack(true);
ZeroMemory(Memory, min_size);
end;
procedure TMemoryMapStream.SetSize(NewSize: integer);
var mult: integer;
begin
if NewSize = Size then exit;
if (fFile <> 0) and not fReadOnly then begin
if NewSize > fRealSize then begin
CloseMMap;
mult := (NewSize - fRealSize) div fGranularity;
if ((NewSize - fRealSize) mod fGranularity) > 0 then
fRealSize := fRealSize + ((mult + 1) * fGranularity)
else
fRealSize := fRealSize + (mult * fGranularity);
SetEOF(fRealSize);
OpenMMap;
SetPointer(Memory, NewSize);
end
else SetPointer(Memory, NewSize);
end;
end;
function TMemoryMapStream.Write(const Buffer; Count: longint): longint;
var pos: longint;
begin
pos := Position;
if (pos < 0) or (Count <= 0) or fReadOnly then begin
result := 0;
exit;
end;
if (pos + Count) > Size then SetSize(pos + Count);
System.Move(Buffer, (pointer(longint(Memory) + pos))^, Count);
pos := pos + Count;
Position := pos;
Result := Count;
end;
procedure TMemoryMapStream.LoadFromFile(const FileName: string);
var f: TFileStream;
begin
f := TFileStream.Create(FileName, fmOpenRead);
try
LoadFromStream(f);
finally
f.Free;
end;
end;
procedure TMemoryMapStream.LoadFromStream(Stream: TStream);
var sz: integer;
begin
if fReadOnly then exit;
sz := Stream.Size;
SetSize(sz);
Stream.Read(Memory^, sz);
Seek(0, soFromBeginning);
end;
procedure TMemoryMapStream.Pack;
begin
doPack(true);
end;
end.
← →
Роман Снегирев (2004-08-30 15:17) [6]Как раз процедуры Read я что то здесь не наблюдаю
← →
wicked © (2004-08-30 15:20) [7]> Роман Снегирев [6]
> Как раз процедуры Read я что то здесь не наблюдаю
см. справку по TCustomMemoryStream или просто попробовать его попользовать....
← →
Игорь Шевченко © (2004-08-30 15:23) [8]
{
Модуль: HSFileMapper
Описание: Класс, обеспечиващий создание файла, проецируемого в память
Автор: Игорь Шевченко
Дата создания: 07.02.2003
История изменений:
}
unit HsFileMapper;
{$IFDEF VER140}
{$WARN SYMBOL_PLATFORM OFF}
{$WARN SYMBOL_DEPRECATED OFF}
{$ENDIF}
{$IFDEF VER150}
{$WARN SYMBOL_PLATFORM OFF}
{$WARN SYMBOL_DEPRECATED OFF}
{$ENDIF}
interface
uses
Windows;
type
THSFileMapper = class
private
FFileHandle : THandle;
FFileSize: DWORD;
FMap: PChar;
FFileName: String;
function GetEndMap: PChar;
public
constructor Create (const AFileName : String);
destructor Destroy; override;
property Map : PChar read FMap;
property EndMap : PChar read GetEndMap;
property FileSize : DWORD read FFileSize;
property FileName : String read FFileName;
end;
implementation
uses
SysUtils;
{ THSFileMapper }
constructor THSFileMapper.Create(const AFileName: String);
var
SizeHighPart : DWORD;
FileMapping : THandle;
begin
inherited Create();
FFileName := AFileName;
FFileHandle := CreateFile (PChar(AFileName), GENERIC_READ,
FILE_SHARE_READ or FILE_SHARE_WRITE,
nil, OPEN_EXISTING, 0, 0);
if FFileHandle = INVALID_HANDLE_VALUE then
RaiseLastWin32Error();
FFileSize := GetFileSize(FFileHandle, @SizeHighPart);
FileMapping := CreateFileMapping (FFileHandle, nil, PAGE_READONLY, 0, 0, nil );
if FileMapping = 0 then
RaiseLastWin32Error();
FMap := MapViewOfFile (FileMapping, FILE_MAP_READ, 0, 0, 0 );
CloseHandle (FileMapping);
if not Assigned(FMap) then
RaiseLastWin32Error();
end;
destructor THSFileMapper.Destroy;
begin
if Assigned(FMap) then
UnmapViewOfFile (FMap);
if FFileHandle <> INVALID_HANDLE_VALUE then
CloseHandle (FFileHandle);
inherited;
end;
function THSFileMapper.GetEndMap: PChar;
begin
Result := FMap + FFileSize;
end;
end.
← →
Роман Снегирев (2004-08-30 15:50) [9]см. справку по TCustomMemoryStream или просто попробовать его попользовать....
а зачем тогда вообще использовать приведенный тобой код если можно создать MemoryStream, загрузить в него файл и читать оттуда
← →
wicked © (2004-08-30 15:58) [10]
> а зачем тогда вообще использовать приведенный тобой код
> если можно создать MemoryStream, загрузить в него файл и
> читать оттуда
а зачем задавать вопросы на форуме, если не понимаешь, что такое наследование и полиморфизм?....
тем более, что дан готовый код - скопируй и попробуй, как работает....
← →
Роман Снегирев (2004-08-30 16:23) [11]а зачем задавать вопросы на форуме, если не понимаешь, что такое наследование и полиморфизм?....
тем более, что дан готовый код - скопируй и попробуй, как работает....
мля...мне нужно читать данные из мапированного файла, а в твоем классе нету метода Read, неужели не понятно что метод Read класса TCustomMemoryStream мне не подходит (равно как и сам TMemoryStream и вообще любой другой Stream ибо уже наступали на эти грабли)
← →
wicked © (2004-08-30 16:28) [12]
> мне нужно читать данные из мапированного файла, а в твоем
> классе нету метода Read, неужели не понятно что метод Read
> класса TCustomMemoryStream мне не подходит
ты уже сел в глубокую лужу... сначала прочти справку, а потом говори... реализация метода Read из TCustomMemoryStream прекрасно подходит, уж поверь...
> (равно как и сам TMemoryStream и вообще любой другой Stream
> ибо уже наступали на эти грабли)
а вот это зря - лучшего механизма я еще не видел... ;)
← →
Роман Снегирев (2004-08-30 17:02) [13]ок, убедил, буду юзать
← →
Роман Снегирев (2004-08-30 17:27) [14]Заюзал, понравилось!!!, а что у него за свойство Granularity и в какое значение его рекомендуется устанавливать?
← →
wicked © (2004-08-31 01:11) [15]
> а что у него за свойство Granularity и в какое значение
> его рекомендуется устанавливать?
это минимальная единица прироста потока - каждый раз, когда происходит запись в конец потока (т. е. поток расширяется), размер файла увеличивается сразу на число байт, кратное Granularity.... после завершения работы с потоком файл обрезается по реальному размеру записанных данных...
т.о., если Granularity будет равно, скажем, 1024 байт, а мы записали в конец потока, скажем, 1500 байт, то размер файла, представляющего этот поток, увеличится сразу на 2048 байт (минимальное число, большее 1500 и кратное 1024).... по умолчанию это значение равно 512 кб...
← →
Роман Снегирев (2004-08-31 09:35) [16]а как это влияет на чтение из файла?
← →
wicked © (2004-08-31 11:24) [17]
> а как это влияет на чтение из файла?
никак...
Страницы: 1 вся ветка
Форум: "WinAPI";
Текущий архив: 2004.10.10;
Скачать: [xml.tar.bz2];
Память: 0.53 MB
Время: 0.052 c