如何监视Textfile并在文本框中连续输出内容

Chr*_*fer 10 c#

我正在制作一个控制游戏服务器的程序.我正在做的一个功能是实时服务器日志文件监视器.

有一个日志文件(一个简单的文本文件),在运行时由服务器更新.

如何连续检查日志文件并在RichTextBox中输出内容?

我做了这个简单的功能只是尝试获取日志的内容.它当然会逐行获取文本并将其输出到我的文本框中.它也会在循环运行时锁定程序,所以我知道它没用.

public void ReadLog()
{
  using (StreamReader reader = new StreamReader("server.log"))
  {
    String line;

    // Read and display lines from the file until the end of the file is reached.
    while ((line = reader.ReadLine()) != null)
    {
      monitorTextBox.AppendText(line + "\n");
      CursorDown();
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

但是,您如何尽可能简单地解决实时监控?

*编辑*

我正在使用Prescots解决方案.好东西.

目前我正在使用sstreamreader将文件中的文本放到我的文本框中.我遇到的问题是,每当我试图访问我的事件处理程序中的任何gui控件时,程序就停止了,没有错误或警告.

我发现它与线程有关.我这样解决了:

private void OnChanged(object source, FileSystemEventArgs e)
{
    if (monitorTextField.InvokeRequired)
    {
        monitorTextField.Invoke((MethodInvoker)delegate { OnChanged(source, e); });
    }
    else
    {
      StreamReader reader = new StreamReader("file.txt");

      monitorTextField.Text = "";
      monitorTextField.Text = reader.ReadToEnd();
      reader.Close();
      CursorDown();
    }
}
Run Code Online (Sandbox Code Playgroud)

现在我唯一的问题是服务器使用了file.txt,所以我无法访问它,因为它"被另一个进程使用".我无法控制这个过程..所以也许我运气不好.

但是当serevr运行时,文件可以在记事本中打开,所以它必须是可能的.也许我可以在更新和读取副本时对文件执行临时副本.不知道...

Pre*_*ott 15

查看System.IO.FileSystemWatcher类:

public static Watch() 
{
    var watch = new FileSystemWatcher();
    watch.Path = @"D:\tmp";
    watch.Filter = "file.txt";
    watch.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite; //more options
    watch.Changed += new FileSystemEventHandler(OnChanged);
    watch.EnableRaisingEvents = true;
}

/// Functions:
private static void OnChanged(object source, FileSystemEventArgs e)
{
    if(e.FullPath == @"D:\tmp\file.txt")
    {
        // do stuff
    }
}
Run Code Online (Sandbox Code Playgroud)

编辑:如果你知道有关该文件的一些细节,你可以处理最有效的方式来获得最后一行.例如,也许当您阅读文件时,您可以消除您所读取的内容,因此下次更新时,您只需抓住其中的任何内容并输出即可.也许您知道一次添加一行,然后您的代码可以立即跳转到文件的最后一行.等等.


ant*_*tfx 5

虽然FileSystemWatcher是最简单的解决方案,但实际上我发现它是不可靠的。通常可以使用新内容更新文件,但是FileSystemWatcher直到几秒钟后才触发事件,并且通常永远不会触发该事件。

我发现解决此问题的唯一可靠方法是使用System.Timers.Timer对象定期检查文件更改并检查文件大小。

我编写了一个小类,在这里演示了这一点:

https://gist.github.com/ant-fx/989dd86a1ace38a9ac58

用法示例

var monitor = new LogFileMonitor("c:\temp\app.log", "\r\n");

monitor.OnLine += (s, e) =>
{
    // WARNING.. this will be a different thread...
    Console.WriteLine(e.Line);
};

monitor.Start();
Run Code Online (Sandbox Code Playgroud)

此处唯一的真正缺点(除了文件大小检查导致的轻微性能延迟外)是因为它使用的System.Timers.Timer是来自不同线程的回调。

如果您使用的是Windows Forms或WPF应用程序,则可以轻松地修改该类以接受SynchronizingObject,以确保事件处理程序事件是从同一线程调用的。