I have an application that must check a folder and read any files that are copied into it. How do I test if a file in that folder is currently being written to? I only want to read files that have had all their data written to them and are closed.
If your files have a known naming convention, run an lsof <filename> against it to check if it is indeed being used by a process. If it isn't, lsof will return a non-zero return code. Please note: If you want to check if the file is being written to by another user, you'll need to run lsof (or fuser ) as root .
Most likely, you'll have to make your program open the file, read a small chunk, close the file, and then wait for a bit before reading again. Even then, there's no guarantee that you won't have the file open when the writing process tries to write.
It ain't clean, but it works:
try
{
using (Stream stream = new FileStream("File.txt"))
{
}
}
catch
{
// Check if file is in use (or whatever else went wrong), and do any user communication that you need to
}
I don't particularly like using exceptions as conditions, but as far as I know this is about the easiest and best (and only reliable) way to do this.
Perhaps opening the file exclusively like this -
System.IO.File.Open(PathToFile, FileMode.Open, FileAccess.ReadWrite, FileShare.None);
That could be placed in a loop with a try/catch until its successful.
Catching exception is expensive you should try to use this:
http://msdn.microsoft.com/en-us/library/system.io.filesystemwatcher.aspx
There's a super clear example on the msdn page. That'll give you nice events on change, created, delete, renamed.
copy the file into the folder and rename when your done catch the rename event and your sure your not reading files that aren't finished yet.
Or you could catch the change events until (this is tricky) they aren't fired anymore.
The only thing I can think of is that a file lock will be put on the file while it is being written to, therefore preventing you from writing to it (throwing a System.IO exception of file being locked by another process), but this is not foolproof. For example, the file could be written to in chunks by opening and closing the file for each chunk.
So you could do this with a try/catch block:
try
{
//opening the file
}
catch(IOException ex)
{
// file is open by another process
}
The file that is written to will typically have write locks on it so if you try to open it for write, you'll fail; but OTOH you may have a process that opens, writes, and closes the file - then repeats. I think the simplest and safest way would be simply to check for files that were written to recently, but not TOO recent (e.g. not in the last 2 seconds or so)
[l.e.] Another point to consider is that if you have a process that writes data in chunck (open-write-close), and you get an exclusive lock for the file (to check that the file is no longer used) - than your external process will fail. I think it's far better to check the timestamps, and only get the exclusive lock after you're reasonably sure that the other process finished writing.
When you open it with System.IO.File.OpenWrite(filename)
, it should throw IOException
.
So, in a try catch, the code being executed in the catch block should tell you the file was open.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With