Delphi - 从每秒更改的日志文件中读取

时间:2014-06-03 12:29:55

标签: delphi

我需要从另一个应用程序不断更改的.log文件中读取。 (经常添加更多数据)

所以我从头开始:

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;

这完全没问题。它会在添加数据的同时实时更新备忘录。但是,我想要在备忘录中看到一些添加的数据。我希望不添加这些行,但仍然可以在没有垃圾线的情况下实时更新备忘录。

最好的方法是什么?

3 个答案:

答案 0 :(得分:6)

您显然需要检查该行是否包含您要包含的内容,并且只有在包含该内容的情况下才添加该内容(如果您不想添加该内容,则不添加该内容,无论哪种情况)。跟踪之前处理过的LogFile中的最后一行也会更有效率,因此每次都可以跳过这些行 - 如果您将变量设置为表单本身的私有成员,它将自动应用程序启动时初始化为0:

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;

所以要完全根据你的代码来处理这个问题:

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;

答案 1 :(得分:1)

我知道自从我上次在这里发布以来已经过了几周,但是我重新编写了整个应用程序,并提出了这段代码,它完美地运行了!

基本上我不在流或字符串列表上调用.free,并且能够设置初始流大小,然后检查它是否已更改,从而获取我需要的数据而不是整个文件!

感谢大家的帮助!

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;

答案 2 :(得分:0)

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;

基本上想出了这个,它的工作非常好。我应该以这种方式遇到任何问题吗?有没有更简洁的方法来做到这一点?