お知らせ

電子会議

ライブラリ

パレット

Delphi FAQ検索

Delphi FAQ一覧

サンプル蔵





FDelphi FAQ
16番会議室「玉石混淆みんなで作るSample蔵」に寄せられたサンプル

"メモリマップトファイル(ストリーム)"

この発言に対し以下のコメントが寄せられています
#00028 ぜえた さん RE:メモリマップトファイル(ストリーム)

メモリマップトファイルを使うためのストリームです。 Memoryプロパティがファイルがマップされたメモリの先頭へのポインタです。 Create の仕方は TFileStream、その後の使い方は TMemoryStream と同じです。 ただし、Createのパラメータ Mode はファイルオープン定数ですが、 fmOpenWrite は指定できません。書き込みだけのメモリは設定できないからです。 メモリマップトファイルの利点 1:ファイルをメモリと同様に扱える。   インターフェースを別々に用意しなくてよい。 2:OSのキャッシュのおかげで、そこそこ速い。 3:メモリに大量のデータをファイルから読み込ませてスワップが発生したとき   ディスク上に同じデータが2つ出来て無駄であるが、それがなくなる。 など。 メモリマップトファイルの欠点 1:いつディスクI/Oが発生するかわからない。 2:OSのキャッシュは賢くない。 3:非同期入出力をつかうことが出来ない。 など。 「メモリマップトファイルを使うな」Inside Windows (1996/10) を参照してください。 #前発言の「共有メモリ」も参考にしてください。 --------------------------------------------------------------------------- unit Streams; interface uses Windows, SysUtils, Classes; type EFMappingError = class(Exception); EFMCreateError = class(EFMappingError); EFMViewError = class(EFMappingError); TFileMappingMemoryStream = class(TMemoryStream) private FMode: WORD; FFileHandle: HFILE; FHandle: THandle; protected function Realloc(var NewCapacity: Longint): Pointer; override; public constructor Create(const FileName: string; Mode: Word); destructor Destroy; override; property FileHandle: HFILE read FFileHandle; property Handle: THandle read FHandle; end; implementation uses Consts; { TFileMappingMemoryStream } constructor TFileMappingMemoryStream.Create(const FileName: string; Mode: WORD); begin FMode := Mode;//先にファイルを開く if FMode = fmCreate then begin FMode := fmOpenReadWrite; FFileHandle := FileCreate(FileName); if FFileHandle = HFILE_ERROR then raise EFCreateError.CreateResFmt(SFCreateError, [FileName]); end else begin FFileHandle := FileOpen(FileName, FMode); if FFileHandle = HFILE_ERROR then raise EFOpenError.CreateResFmt(SFOpenError, [FileName]); end; inherited Create; SetSize(GetFileSize(FFileHandle, nil)); end; destructor TFileMappingMemoryStream.Destroy; begin inherited Destroy; if FFileHandle <> 0 then CloseHandle(FFileHandle);//後からファイルを閉じる end; function TFileMappingMemoryStream.Realloc(var NewCapacity: Longint): Pointer; const ProtectMode: array[0..2] of DWORD = ( PAGE_READONLY, PAGE_READWRITE, PAGE_READWRITE); ViewAccessMode: array[0..2] of DWORD = ( FILE_MAP_READ, FILE_MAP_WRITE, FILE_MAP_WRITE); begin Result := Memory; if NewCapacity <> Capacity then begin if Capacity <> 0 then begin UnmapViewOfFile(Memory); CloseHandle(FHandle); Result := nil; end; if NewCapacity <> 0 then begin FHandle := CreateFileMapping(FFileHandle, nil, ProtectMode[FMode and $0003], 0, NewCapacity, nil); try if FHandle = 0 then raise EFMCreateError.Create('Could not resize file-mapping object'); Result := MapViewOfFile(FHandle, ViewAccessMode[FMode and $0003], 0, 0, NewCapacity); if Result = nil then begin CloseHandle(FHandle); raise EFMViewError.Create('Could not map view of file'); end; except //Reallocが失敗したとき元の大きさに戻す FHandle := CreateFileMapping(FFileHandle, nil, ProtectMode[FMode and $0003], 0, Capacity, nil); if FHandle = 0 then raise; Result := MapViewOfFile(FHandle, ViewAccessMode[FMode and $0003], 0, 0, Capacity); if Result = nil then CloseHandle(FHandle); raise; end; end; end; end; end. --------------------------------------------------------------------------- なお、Delphi2.0 では、TMemoryStream にバグがあります。 SetSize が失敗するとすべてのメモリが失われるというバグです。 ソースをお持ちのかたは次のように直してください(Delphi3 VCLより)。 procedure TMemoryStream.SetSize(NewSize: Longint); begin // Clear;//削除 if FPosition > NewSize then Seek(0, soFromEnd);//追加 SetCapacity(NewSize); FSize := NewSize; end; ぜえた (QZC05100) Original document by ぜえた 氏 ID:(QZC05100)



ここにあるドキュメントは NIFTY SERVEの Delphi Users' Forum の16番会議室「玉石混淆みんなで作るSample蔵」に投稿されたサンプルです。これらのサンプルはボーランド株式会社がサポートする公式のものではありません。また、必ずしも動作が検証されているものではありません。これらのサンプルを使用したことに起因するいかなる損害も投稿者、およびフォーラムスタッフはその責めを負いません。使用者のリスクの範疇でご使用下さい。

Copyright 1996-2002 Delphi Users' Forum