Entwickler-Ecke

Dateizugriff - Shared-Read-Zugriff auf Datei (tail -f)


bjrtap26 - Do 24.03.11 10:09
Titel: Shared-Read-Zugriff auf Datei (tail -f)
Hallo!

Ich habe eine Datei mit Text, in diese Datei wird laufend neuer Text geschrieben von einem anderen Programm.
Nun möchte ich mit meiner App auf diese Datei lesend zugreifen, und jedesmal wenn eine Zeile dazukommt, diese auswerten. Das entspricht ziemlich genau dem Tail -f unter linux.

Ich habe bereits eine Lösung (dieses Parsen der Datei läuft in einem eigenen Thread):


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
procedure TParseThread.execute;
var AHStream : THandleStream;
    AFileHandle : THandle;
    str, nstr: string;
    buf: TBytes;
    enc: TEncoding;
    LOffset: Integer;
    s: int64;
begin
  if not FileExists(pfile) then  Exit;

  AFileHandle := CreateFile(PChar(pfile), GENERIC_READ, FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);

  if AFileHandle <> INVALID_HANDLE_VALUE then begin
    AHStream := THandleStream.Create(AFileHandle);

    s := ahstream.Size;
    enc:= nil;
    setlength(buf, s);
    ahstream.ReadBuffer(Pointer(buf)^, s);
    LOffset := TEncoding.GetBufferEncoding(buf, enc);
    str := enc.GetString(buf, loffset, s-loffset);

    str := '';
    repeat
      while ahstream.Position = ahstream.Size do application.ProcessMessages;
      sleep(10);

      setlength(buf, 1);
      ahstream.ReadBuffer(pointer(buf)^, 1);
      nstr := enc.GetString(buf, 01);
      if nstr <> #10 then str :=  str + nstr;
      if nstr = #13 then begin

        // HIER PARSEN
        parse(str);

        str := '';
      end;
    until false;

    FreeAndNil(AHStream);
    CloseHandle(AFileHandle);
  end;
end;



Wie ihr seht sehr unelegant, ich habe busy waiting drin und lese immer nur ein Zeichen...

Das muss doch besser gehen!
Wie gesagt ich brauche immer ganze Zeilen zum auswerten für meinen Parser.

Jemand ne Idee?
Gruß
B

Moderiert von user profile iconMartok: Code- durch Delphi-Tags ersetzt


jaenicke - Do 24.03.11 11:13

Hallo und :welcome:

Also erstens nimm das Application.ProcessMessages raus...
Das ist dafür, dass z.B. die GUI nicht hängt, weil die Messages nicht abgearbeitet werden. Ein Thread ist aber genau dafür da, dass er eben nebenbei läuft. Da ist das Sleep statt Application.ProcessMessages schon korrekt.

Zweitens kannst du dich über Änderungen an Dateien informieren lassen:
http://msdn.microsoft.com/en-us/library/aa365261(v=vs.85).aspx

Je nach Anwendung kann es auch Sinn machen schlicht WriteFile zu hooken und so jeden Schreibvorgang direkt mitzubekommen.