How to monitor a folder for new files from your C# application
Suppose that you need to write a C# application to run in an environment where there are many batch applications running and creating files as their output.
Your application is one of them and is required to process files produced by others. How are you going to know from your C# application when these files are ready?
In this post, I document the use of a .Net facility that can help you achieve that.
The FileInputMonitor class
Let us create a sample use case. Suppose there is a folder which other applications will deposit their file output on a daily basic. The naming convention of the file will be report-for-<CURRENT_DATE-YYYY-MM-DD>. For instance, on 7th April 2012, the file will be named as report-for-2012-04-07.
The following FileInputMonitor
class is an implementation for the sample use case.
using System; using System.IO; using System.Text; using System.Threading; public class FileInputMonitor { private FileSystemWatcher fileSystemWatcher; private string folderToWatchFor = AppDomain.CurrentDomain.SetupInformation.ApplicationBase + "toTechcoil"; public FileInputMonitor() { fileSystemWatcher = new FileSystemWatcher(folderToWatchFor); fileSystemWatcher.EnableRaisingEvents = true; // Instruct the file system watcher to call the FileCreated method // when there are files created at the folder. fileSystemWatcher.Created += new FileSystemEventHandler(FileCreated); } // end FileInputMonitor() private void FileCreated(Object sender, FileSystemEventArgs e) { if (e.Name == "report-for-" + System.DateTime.Now.ToString("yyyy-MM-dd")) { ProcessFile(e.FullPath); } // end if } // end public void FileCreated(Object sender, FileSystemEventArgs e) private void ProcessFile(String fileName) { FileStream inputFileStream; while (true) { try { inputFileStream = new FileStream(fileName, FileMode.Open, FileAccess.ReadWrite); StreamReader reader = new StreamReader(inputFileStream); Console.WriteLine(reader.ReadToEnd()); // Break out from the endless loop break; } catch (IOException) { // Sleep for 3 seconds before trying Thread.Sleep(3000); } // end try } // end while(true) } // end private void ProcessFile(String fileName) } // end public class FileInputMonitor
Monitoring whether new files are created in a folder with System.IO.FileSystemWatcher
When an instance of FileInputMonitor
is created, we also create an instance of System.IO.FileSystemWatcher
class, passing it the directory path of the folder to monitor.
After creating an instance of the FileSystemWatcher, we proceed to configure it. In order to enable the FileSystemWatcher
instance to notify our application when files are created in the folder, we must first set its EnableRaisingEvents
property to true.
We then add a System.IO.FileSystemEventHandler
delegate to the Created
event so that control can be delegated to the FileCreated
method of our FileInputMonitor
class whenever a new file is created.
Checking whether an expected file is ready for processing
When the FileCreated
method is executed, we check whether the new file is what our application wants via the Name property of the System.IO.FileSystemEventArgs
instance. If the file is designated for our application, the ProcessFile
method is called to process the file.
In the ProcessFile
method, we attempt to get an instance of System.IO.FileStream
with ReadWrite
access to read from the file in an infinite loop. This is because the batch application may still be writing to the file when our application received notification of the new file.
In the event when the instance of FileStream
cannot be retrieved, the application will wait for 3 seconds via a call to Thread.Sleep. Upon success acquisition of the FileStream instance, the code reads from the file, output it to console and break out of the infinite loop.
Using the FileInputMonitor class
To conclude this post, the following is a program that maintains an instance of the FileInputMonitor
to monitor the toTechcoil folder that is in the same directory as the executable.
public class Program { public static void Main(string[] args) { FileInputMonitor fileInputMonitor = new FileInputMonitor(); Console.Read(); } // end public static void Main(string[] args) } // end public class Program
4 Comments
This is very helpful, thank you!
Hi Dan,
You are welcomed. 🙂
this info is very useful
Hi Vikas,
Glad that this article had helped you. 🙂