Reputation: 111
I need to read from a .log file that is constantly changing by another application. (more data being added frequently)
So I have this to begin with:
var
LogFile: TStrings;
Stream: TStream;
begin
LogFile := TStringList.Create;
try
Stream := TFileStream.Create(Log, fmOpenRead or fmShareDenyNone);
try
LogFile.LoadFromStream(Stream);
finally
Stream.Free;
end;
while LogFile.Count > Memo1.Lines.Count do
Memo1.Lines.Add(LogFile[Memo1.Lines.Count]);
finally
LogFile.Free;
end;
end;
This works perfectly fine. It updates the memo at real time with the data being added. However some of the data being added I don't want to see in the memo. I wish to not add these lines, but still have the memo updated at real time without the junk lines.
What is the best way to go about this?
Upvotes: 3
Views: 2531
Reputation: 111
I know its been a couple of weeks since i last posted here, but i rewrote the entire application and came up with this piece of code, which is working perfectly!
Basically i do not call .free on the stream or stringlist and am able to set the initial stream size then check if its changed, hence getting the data i need and not the entire file!
Thanks everyone for helping!
procedure TForm1.GetEndLogFile;
begin
LogFile := TStringList.Create;
Stream := TFileStream.Create('C:\Users\John\Documents\chat.log', fmOpenRead or fmShareDenyNone);
LogFile.LoadFromStream(Stream);
i := Stream.Size;
end;
procedure TForm1.LogFileRefresh;
var
buf: string;
begin
if i <> Stream.Size then
begin
SetLength(buf, Stream.Size);
Stream.Seek(i, Stream.Size);
Stream.Read(buf[1], Stream.Size);
i := Stream.Size;
Memo1.Lines.Append(Buf);
//ShowMessage(buf);
end;
end;
Upvotes: 1
Reputation: 125728
You'd clearly need to check to see if the line has content you want to include, and only add it if it has that content (or not add it if you don't want to include it, whichever is the case). It would also be much more efficient to keep track of the last line in the LogFile
you processed previously, so you could skip those lines each time - if you make the variable a private member of the form itself, it will automatically be initialized to 0 when your application starts:
type
TForm1 = class(TForm)
//... other stuff added by IDE
private
LastLine: Integer;
end;
// At the point you need to add the logfile to the memo
for i := LastLine to LogFile.Count - 1 do
begin
if ContentWanted(LogFile[i]) then
Memo1.Lines.Append(LogFile[i]);
Inc(LastLine);
end;
So to handle this completely based on your code:
type
TForm1 = class(TForm)
//... IDE stuff here
private
FLastLogLine: Integer;
procedure ProcessLogFile;
public
// Other stuff
end;
procedure TForm1.ProcessLogFile;
var
Log: TStringList;
LogStream: TFileStream;
i: Integer;
begin
Log := TStringList.Create;
try
LogStream := TFileStream.Create(...);
try
Log.LoadFromStream(LogStream);
finally
LogStream.Free;
end;
for i := FLastLogLine to Log.Count - 1 do
if Pos('[Globals] []', Log[i]) <>0 then
Memo1.Lines.Append(Log[i]);
// We've now processed all the lines in Log. Save
// the last line we processed as the starting point
// for the next pass.
FLastLogLine := Log.Count - 1;
finally
Log.Free;
end;
end;
procedure TForm1.Timer1Timer(Sender: TObject);
begin
Timer1.Enabled := False;
try
ProcessLogFile;
finally
Timer1.Enabled := True;
end;
end;
end;
Upvotes: 6
Reputation: 111
procedure TForm1.GetEndLogFile;
var
LogFile: TStrings;
Stream: TStream;
begin
LogFile := TStringList.Create;
try
Stream := TFileStream.Create(LogFile, fmOpenRead or fmShareDenyNone);
try
LogFile.LoadFromStream(Stream);
EndOfFile := LogFile.Count;
finally
Stream.Free;
end;
finally
LogFile.Free;
end;
end;
procedure TForm1.LogFileRefresh;
var
LogFile2: TStrings;
Stream2: TStream;
i: Integer;
begin
LogFile2 := TStringList.Create;
try
Stream2 := TFileStream.Create(LogFile, fmOpenRead or fmShareDenyNone);
try
LogFile2.LoadFromStream(Stream2);
finally
Stream2.Free;
end;
for i := EndOfFile to LogFile2.Count -1 do
begin
if Pos('[Globals] []',LogFile2[i])<>0 then
Memo1.Lines.Append(LogFile2[i]);
Inc(EndOfFile);
end;
finally
LogFile2.Free
end;
end;
Basically came up with this, and its working perfectly fine. Should i run into any problems this way? Is there a neater way to do this?
Upvotes: 0