unit myStream; //{$DEFINE DEBUG} interface uses Classes, SysUtils, Windows; type TFileStreamW = class(THandleStream) private function F_GetIsCreated : Boolean; public constructor Create(const FileName: WideString; Mode: Word); overload; destructor Destroy; override; property IsCreated : Boolean read F_GetIsCreated; end; TMyFileStream = class(THandleStream) private function F_GetAnsiChar: AnsiChar; function F_GetIsCreated : Boolean; public constructor Create(FileName: WideString; AccessMode, ShareMode: DWORD); overload; constructor Create(FileName: WideString); overload; destructor Destroy; override; property Char: AnsiChar read F_GetAnsiChar; property IsCreated : Boolean read F_GetIsCreated; end; function gfniStreamFind(AStream : TStream; iStart : Int64; pData : PAnsiChar; iCount : Integer) : Int64; implementation uses {$IFDEF DEBUG} myDebug, {$ENDIF} // Forms, RTLConsts; {TFileStreamW} constructor TFileStreamW.Create(const FileName: WideString; Mode: Word); //TFileStreamのUnicode版  var li_AccessMode : DWORD; li_ShareMode : DWORD; begin if (Mode = fmCreate) then begin inherited Create(CreateFileW( PWideChar(FileName), //ファイル名 GENERIC_READ or GENERIC_WRITE, //アクセスモード 0, //共有モード nil, //セキュリティ OPEN_ALWAYS, //作成方法 FILE_ATTRIBUTE_NORMAL, //ファイル属性 0 //テンプレート )); end else begin //アクセスモード li_AccessMode := GENERIC_READ; if ((Mode and fmOpenWrite) <> 0) then begin li_AccessMode := li_AccessMode or GENERIC_WRITE; end; {$WARN SYMBOL_PLATFORM OFF} //共有モード li_ShareMode := 0; if (Mode >= fmShareExclusive) then begin Dec(Mode, $10); end; if ((Mode and (fmShareDenyRead - $10)) <> 0) then begin //読み込みは禁止=書き込みはOK li_ShareMode := FILE_SHARE_WRITE; end; if ((Mode and (fmShareDenyWrite - $10)) <> 0) then begin //書き込みは禁止=読み込みはOK li_ShareMode := li_ShareMode or FILE_SHARE_READ; end; {$WARN SYMBOL_PLATFORM ON} inherited Create(CreateFileW( PWideChar(FileName), li_AccessMode, li_ShareMode, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0 )); end; // if (FHandle = Integer(INVALID_HANDLE_VALUE)) then begin //エラーメッセージはUnicode対応ではない。 // raise EFCreateError.CreateResFmt(@SFCreateError, [FileName]); // end; end; destructor TFileStreamW.Destroy; begin CloseHandle(FHandle); inherited Destroy; end; function TFileStreamW.F_GetIsCreated : Boolean; begin Result := (FHandle <> Longint(INVALID_HANDLE_VALUE)); end; //------------------------------------------------------------------------------ {TMyFileStream} { fdwAccess ファイルへのアクセスの種類を指定します。アプリケーションは、 読み取 りアクセス、 書き込みアクセス、 読み書きアクセス、 デバイス問い合わせ アクセスを取得できます。このパラメータには、 次に示す値の組み合わせ を指定してください。読み書きアクセスを取得するには、 GENERIC_READと GENERIC_WRITEの両方を指定しなければなりません。 0 アプリケーションは、 デバイスに実際にアクセスせずにデバイスの属性を 問い合わせることができます。 GENERIC_READ ファイルへの読み取りアクセスを指定します。ファイルからのデータの読 み取りと、 ファイル ポインタの移動が可能です。 GENERIC_WRITE ファイルへの書き込みアクセスを指定します。ファイルからのデータの読 み書きと、 ファイル ポインタの移動が可能です。 fdwShareMode 作成するファイルの共有方法を指定します。このパラメータには、 次の値 の組み合わせを指定します。 0 ファイルを共有できないようにします。 FILE_SHARE_READ ファイルへの読み取りアクセスのために、 ほかのオープン操作を実行 できます。 CreateFile関数がメールスロットのクライアント端点をオープンして いる場合には、 このフラグを指定してください。 FILE_SHARE_WRITE ファイルへの書き込みアクセスのために、 ほかのオープン操作を実行 できます。 } constructor TMyFileStream.Create(FileName: WideString; AccessMode, ShareMode: DWORD); var li_CreateMode: DWORD; lh_Handle : THandle; begin if ((AccessMode and GENERIC_WRITE) <> 0) then begin li_CreateMode := OPEN_ALWAYS; end else begin li_CreateMode := OPEN_EXISTING; end; lh_Handle := CreateFileW( PWidechar(FileName), //ファイル名 AccessMode, //アクセスモード ShareMode, //共有モード nil, //セキュリティ li_CreateMode, //作成方法 FILE_ATTRIBUTE_NORMAL, //ファイル属性 0 //テンプレート ); inherited Create(lh_Handle); end; constructor TMyFileStream.Create(FileName: WideString); begin Create(FileName, GENERIC_READ, FILE_SHARE_READ); end; destructor TMyFileStream.Destroy; begin CloseHandle(FHandle); inherited Destroy; end; function TMyFileStream.F_GetAnsiChar: AnsiChar; begin Read(Result, 1); end; function TMyFileStream.F_GetIsCreated : Boolean; begin Result := (FHandle <> Longint(INVALID_HANDLE_VALUE)); end; //------------------------------------------------------------------------------ function gfniStreamFind(AStream : TStream; iStart : Int64; pData : PAnsiChar; iCount : Integer) : Int64; {2011-05-16: iStartは0ベースのスタートポジション } var i : Int64; k : Integer; l_Dat : AnsiChar; begin Result := -1; if (iCount <= 0) or (iStart < 0) or (iStart >= AStream.Size) then begin Exit; end; i := iStart; while (i < AStream.Size) do begin // Application.ProcessMessages; //検索チェック AStream.Position := i; AStream.Read(l_Dat, 1); //myDebug.gpcDebug([i, l_Dat, pData[0]]); if (l_Dat = pData[0]) then begin if (iCount = 1) then begin Result := i; Exit; end else begin try //pData[0]は既に一致しているので1から始める for k := 1 to iCount-1 do begin AStream.Position := i + k; AStream.Read(l_Dat, 1); if (l_Dat <> pData[k]) then begin Abort; //finallyに飛ぶ end; end; Result := AStream.Position - iCount; Exit; except //単なるラベル代わり end; end; end; Inc(i); end; end; end.