C# 如何监控文本文件并在文本框中连续输出内容?
我正在制作一个控制游戏服务器的程序。我正在做的功能之一是一个实时服务器日志文件监视器 有一个日志文件(一个简单的文本文件),在运行时由服务器更新 如何连续检查日志文件并将其内容输出到RichTextBox中 我做了这个简单的函数,只是尝试获取日志的内容。当然,它只需逐行获取文本并将其输出到我的文本框中。而且只要循环运行,它就会锁定程序,所以我知道这是无用的C# 如何监控文本文件并在文本框中连续输出内容?,c#,C#,我正在制作一个控制游戏服务器的程序。我正在做的功能之一是一个实时服务器日志文件监视器 有一个日志文件(一个简单的文本文件),在运行时由服务器更新 如何连续检查日志文件并将其内容输出到RichTextBox中 我做了这个简单的函数,只是尝试获取日志的内容。当然,它只需逐行获取文本并将其输出到我的文本框中。而且只要循环运行,它就会锁定程序,所以我知道这是无用的 public void ReadLog() { using (StreamReader reader = new StreamReade
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();
}
}
}
但是,您将如何尽可能简单地解决实时监控问题
***编辑***
我用的是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();
}
}
现在我唯一的问题是服务器使用了file.txt,所以我无法访问它,因为它“正在被另一个进程使用”。我无法控制这个过程,所以也许我运气不好
但是,当服务器运行时,文件可以在记事本中打开,所以无论如何,这是可能的。也许我可以在文件更新并读取副本时对其进行临时复制。我不知道。尝试添加一个计时器,并将
计时器设置为间隔1秒。在定时器上。勾选运行该函数
private void myTimer_Tick(object sender, EventArgs e)
{
ReadLog();
}
查看课程:
编辑:如果你知道关于文件的一些细节,你可以用最有效的方法得到最后一行。例如,当您读取文件时,您可能会擦除您所读取的内容,因此下次更新时,您只需获取其中的内容并输出。也许您知道一次添加一行,那么您的代码可以立即跳到文件的最后一行。等等。按照@Prescott的建议,使用文件系统观察程序。并确保以适当的模式打开文件(FileShare.ReadWrite
似乎合适),因为文件可能仍由服务器打开。如果在另一个进程仍在使用该文件时尝试以独占方式打开该文件,则打开操作将失败
另外,为了获得一点性能,您可以记住您已经读取文件的最后位置,并且只读取新的部分。尽管FileSystemWatcher
是最简单的解决方案,但我发现它实际上不可靠。。通常,可以使用新内容更新文件,但FileSystemWatcher
直到几秒钟后才会触发事件,而且通常从不触发事件
我发现唯一可靠的方法是使用System.Timers.Timer
对象定期检查文件的更改,并检查文件大小
我在这里编写了一个小类来演示这一点:
示例用法
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();
这里唯一真正的缺点(除了文件大小检查导致的轻微性能延迟)是,因为它使用System.Timers.Timer
回调来自不同的线程
如果您使用的是Windows窗体或WPF应用程序,您可以轻松修改该类以接受同步对象,这将确保从同一线程调用事件处理程序事件。在另一篇文章中使用此答案
这是一个非常有效的方法,它每秒检查一次文件大小是否已更改
您可以在另一个线程上运行它(或转换为异步代码),但在任何情况下,您都需要将文本打包回主线程以附加到文本框。使用计时器。。。每10秒或5秒检查一次…谢谢!那会有很大帮助。我对这个很陌生。。。现在我遇到了获取“方法必须有一个返回类型”的noob问题,如果我将Watch()类设置为“public void Watch()”,则不会发生这种情况。我可能是在错误的地方或方式创建它。我把它放在我的“公共部分类MYPROGRAM:Form”中啊,是的,对不起,我写周围的代码非常快。您可以删除watcher代码,并在适当的时候将其放入您的代码中,而不必像我上面提到的那样放入Watch()函数中。谢谢!我刚刚在第一个问题中添加了一些信息(这里是新的..这样做是否违反了任何规则?)如果您的问题得到了回答,您可能希望将其标记为已回答并开始一个新问题。如果我使用StreamReader,它会变得更干净吗?我想为了寻找一个特定的位置,你必须直接访问底层的FileStream
(通过position
属性)。因此,首先创建文件流
,转到正确的位置,在流的顶部构造一个流读取器
,读取数据,然后再次从文件流
获取最终位置。(我没有试过,我希望它能像描述的那样工作…)
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();