Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FileSystemWatcher - is File ready to use

When a file is being copied to the file watcher folder, how can I identify whether the file is completely copied and ready to use? Because I am getting multiple events during file copy. (The file is copied via another program using File.Copy.)

like image 801
snober Avatar asked Sep 04 '12 16:09

snober


People also ask

What is the use of FileSystemWatcher class in .NET framework?

Use FileSystemWatcher to watch for changes in a specified directory. You can watch for changes in files and subdirectories of the specified directory. You can create a component to watch files on a local computer, a network drive, or a remote computer.

What is a FileSystemWatcher?

IDG. The FileSystemWatcher class in the System.IO namespace can be used to monitor changes to the file system. It watches a file or a directory in your system for changes and triggers events when changes occur. In order for the FileSystemWatcher to work, you should specify a directory that needs to be monitored.

Which of the following are types of changes that can be detected by the FileSystemWatcher?

The FileSystemWatcher lets you detect several types of changes in a directory or file, like the 'LastWrite' date and time, changes in the size of files or directories etc. It also helps you detect if a file or directory is deleted, renamed or created.

Which event handler is suggested when a file is changed in C#?

FileSystemWatcher.Created Event (System.IO) Occurs when a file or directory in the specified Path is created.


2 Answers

When I ran into this problem, the best solution I came up with was to continually try to get an exclusive lock on the file; while the file is being written, the locking attempt will fail, essentially the method in this answer. Once the file isn't being written to any more, the lock will succeed.

Unfortunately, the only way to do that is to wrap a try/catch around opening the file, which makes me cringe - having to use try/catch is always painful. There just doesn't seem to be any way around that, though, so it's what I ended up using.

Modifying the code in that answer does the trick, so I ended up using something like this:

private void WaitForFile(FileInfo file)
{
    FileStream stream = null;
    bool FileReady = false;
    while(!FileReady)
    {
        try
        {
            using(stream = file.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.None)) 
            { 
                FileReady = true; 
            }
        }
        catch (IOException)
        {
            //File isn't ready yet, so we need to keep on waiting until it is.
        }
        //We'll want to wait a bit between polls, if the file isn't ready.
        if(!FileReady) Thread.Sleep(1000);
    }
}
like image 75
Tacroy Avatar answered Sep 27 '22 21:09

Tacroy


Here is a method that will retry file access up to X number of times, with a Sleep between tries. If it never gets access, the application moves on:

private static bool GetIdleFile(string path)
{
    var fileIdle = false;
    const int MaximumAttemptsAllowed = 30;
    var attemptsMade = 0;

    while (!fileIdle && attemptsMade <= MaximumAttemptsAllowed)
    {
        try
        {
            using (File.Open(path, FileMode.Open, FileAccess.ReadWrite))
            {
                fileIdle = true;
            }
        }
        catch
        {
            attemptsMade++;
            Thread.Sleep(100);
        }
    }

    return fileIdle;
}

It can be used like this:

private void WatcherOnCreated(object sender, FileSystemEventArgs e)
{
    if (GetIdleFile(e.FullPath))
    {
        // Do something like...
        foreach (var line in File.ReadAllLines(e.FullPath))
        {
            // Do more...
        }
    }
}
like image 38
Chris Schiffhauer Avatar answered Sep 27 '22 19:09

Chris Schiffhauer