I need to watch a directory for image files(jpeg,png,tif,gif,bmp) and process new files placed there.Im trying to implement this using FileSystemWatcher
private void watch()
{
FileSystemWatcher watcher = new FileSystemWatcher();
watcher.Path = path;
watcher.Filter = "*.*";
watcher.Changed += new FileSystemEventHandler(OnChanged);
watcher.EnableRaisingEvents = true;
}
But how can i make sure that the file is copied in full and there is no handle locking the file before trying to open it?
To process a file once its fully copied you need to add the below filter:
watcher.NotifyFilter = NotifyFilters.LastWrite;
This will notify once the file is fully copied into the directory
Ref : FileSystemWatcher
For multi file filter you have two options:
watcher.Filter = "*.*";
or use the following constructor:
FileSystemWatcher watcher = new FileSystemWatcher("path","*.*");
The only process that knows whether or not the file is fully copied is the one doing the copying. Think about it - a file is merely a stream of data. Without additional information, there's no way to know how much data is supposed to be in the file.
Without some form of communication that the file is fully copied, the only thing any other process can do is guess based upon the the file not being open and not being written to any more, and then hope the guess is correct. Anything like this that relies on the file no longer being written to nor held open by any other process can not handle failures. If a file is being copied by a process such as FTP and the network connection drops in the middle of copying a file for any reason, a "guess-and-hope" process will incorrectly identify the file as complete.
There are several methods to solve this problem, but they all require the sending process to send a signal of some type to the receiver that the file is done.
You can have the sending process send a "DONE" file - after sending DataFile
, the sending process then sends a zero-length file called DataFile.done
. Once you see DataFile.done
, you know for certain that DataFile
has been fully copied. If you don't see DataFile.done
, DataFile
isn't fully copied.
You can also have the sending process rename the file - if your underlying OS and file system support atomic file rename operations. You can have your sending process initially send DataFile.copying
, and when the copying is complete rename the file to DataFile
. Any file that has a .copying
extension is still in the process of being copied.
Some data file formats also indicate complete files. PDF files follow a specified format and you can tell if they're complete. XML files can be constructed in a way that you can tell if they're complete. But this is not an efficient solution as it requires parsing the contents of the file, and if the files are large or there are performance requirements the continual reading of each file multiple times can result in serious IO performance problems.
Again, you can't solve this problem without the sending process sending some sort of DONE flag. The receiving process simply doesn't have enough data to do anything other than guess when the file is done, and then it can only hope it's made the correct guess.
Systems that rely on guessing and hoping generally aren't very reliable.