How to monitor Textfile and continuously output content in a textbox?

Check out the System.IO.FileSystemWatcher class:

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
    }
}

Edit: if you know some details about the file, you could handle the most efficent way to get the last line. For example, maybe when you read the file, you can wipe out what you've read, so next time it's updated, you just grab whatever is there and output. Perhaps you know one line is added at a time, then your code can immediately jump to the last line of the file. Etc.


Although the FileSystemWatcher is the most simple solution I have found it to be unreliable in reality.. often a file can be updated with new contents but the FileSystemWatcher does not fire an event until seconds later and often never.

The only reliable way I have found to approach this is to check for changes to the file on a regular basis using a System.Timers.Timer object and checking the file size.

I have written a small class that demonstrates this available here:

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

Example Usage

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();

The only real disadvantage here (apart from a slight performance delay caused by file size checking) is that because it uses a System.Timers.Timer the callback comes from a different thread.

If you are using a Windows Forms or WPF app you could easily modify the class to accept a SynchronizingObject which would ensure the event handler events are called from the same thread.


As @Prescott suggested, use a FileSystemWatcher. And make sure, you open the file with the appropriate FileShare mode (FileShare.ReadWrite seems to be appropriate), since the file might still be opened by the server. If you try to open the file exclusively while it is still used by another process, the open operation will fail.

Also in order to gain a bit of performance, you could remember the last position up to which you already have read the file and only read the new parts.


Use this answer on another post c# continuously read file.

This one is quite efficient, and it checks once per second if the file size has changed.

You can either run it on another thread (or convert to async code), but in any case you would need to marshall the text back to the main thread to append to the textbox.

Tags:

C#