首页  编辑  

一个文件被改变之后如何立即知道

Tags: /超级猛料/Stream.File.流、文件和目录/文件操作/   Date Created:

问题:我想知道一个文件是否被改变,如何监视?一个方法是使用Timer不停监测,这样不精确并且来非CPU时间,那么有没有更好的方法呢?

来自Luke有:

TFileChangeNotificationStatus=(fnsIdle,fnsError,fnsRunning);

 TFileChangeNotification=record

   PathName:string;

   WatchSubtree:boolean;

   NotifyFilter:DWORD;

   Status:TFileChangeNotificationStatus;

   Changes:DWORD;

   wndHandle:HWND;

   NotificationMessage:DWORD;

 end;

 TFileChangesMultipleWatcher = class(TThread)

 private

   { Private declarations }

   FMutex:integer;

   FObjectsArray:array[0..(WAITOBJECTSCOUNT-1)]of integer;

 protected

   procedure Execute; override;

 public

   Notification:TFileChangeNotification;

   constructor Create(Suspended:boolean);

   destructor Destroy; override;

   procedure Init;

   procedure Stop;

 end;

constructor TFileChangesMultipleWatcher.Create;

var guid:TGUID;

begin

 inherited;

 coCreateGuid(guid);

 FMutex:=CreateMutex(nil,False,PChar('TFCMW.'+GuidToString(guid)));

 WaitForSingleObject(FMutex,INFINITE);

 if FMutex<>0 then FObjectsArray[0]:=FMutex;

 FreeOnTerminate:=True;

end;

//

destructor TFileChangesMultipleWatcher.Destroy;

begin

 inherited;

 {$ifdef DEBUGGING_FILECHANGES} writeln(Notification.PathName,' -DESTROY'); {$endif}

end;

//

procedure TFileChangesMultipleWatcher.Init;

begin

 with Notification do begin

   PathName:='';

   WatchSubtree:=False;

   NotifyFilter:=0;

   Status:=fnsIdle;

   Changes:=0;

   wndHandle:=0;

   NotificationMessage:=WM_USER;

 end;

end;

//

procedure TFileChangesMultipleWatcher.Stop;

begin

 Terminate;

 ReleaseMutex(FMutex);

end;

//

procedure TFileChangesMultipleWatcher.Execute;

var WaitStatus,hChanges:DWORD;

   Go:boolean;

begin

 try while (not Terminated) do begin

       with Notification do begin

hChanges:=FindFirstChangeNotification(PChar(PathName),WatchSubtree,NotifyFil

ter);

         {$ifdef DEBUGGING_FILECHANGES} writeln('Notification Handle is

',hChanges); {$endif}

         if (hChanges<>INVALID_HANDLE_VALUE) then try

           FObjectsArray[1]:=hChanges;

           Status:=fnsRunning;

           Go:=True;

           while (Go) do begin

             {$ifdef DEBUGGING_FILECHANGES} writeln('WaitForSingleObject');

{$endif}

WaitStatus:=WaitForMultipleObjects(WAITOBJECTSCOUNT,@FObjectsArray,False,INF

INITE);

             file://if Terminated then exit;

             case WaitStatus of

               WAIT_ABANDONED:begin

                 {$ifdef DEBUGGING_FILECHANGES} writeln('WAIT_ABANDONED');

{$endif}

               end;

               WAIT_OBJECT_0:begin

                  exit;

                 {$ifdef DEBUGGING_FILECHANGES} writeln('WAIT_OBJECT_0');

{$endif}

               end;

               WAIT_OBJECT_0+1:begin

                 inc(Changes);

                 if (wndHandle<>0) then

PostMessage(wndHandle,NotificationMessage,Changes,NotificationMessage+Change

s);

                 {$ifdef DEBUGGING_FILECHANGES} writeln('WAIT_OBJECT_1');

{$endif}

               end;

               WAIT_TIMEOUT:begin

                 {$ifdef DEBUGGING_FILECHANGES} writeln('WAIT_TIMEOUT');

{$endif}

               end;

             end;

             Sleep(100);

             Go:=FindNextChangeNotification(hChanges);

           end;

         finally

           {$ifdef DEBUGGING_FILECHANGES} writeln('FINALLY 1'); {$endif}

           FindCloseChangeNotification(hChanges);

         end else begin

           Status:=fnsError;

           {$ifdef DEBUGGING_FILECHANGES} writeln('STATUS ERROR'); {$endif}

         end;

       end;

     end;

 finally

   {$ifdef DEBUGGING_FILECHANGES} writeln('FINALLY 2'); {$endif}

   ReleaseMutex(FMutex);

 end;

 {$ifdef DEBUGGING_FILECHANGES} writeln('BYE!'); {$endif}

end;

//