When files and folders do not exist, FileSystemWatcher cannot monitor file changes? It's fine if you listen recursively

When files and folders do not exist, FileSystemWatcher cannot monitor file changes? It's fine if you listen recursively

When you need to monitor file or folder changes, use

FileSystemWatcher
It can be done. but,
FileSystemWatcher
The monitoring of the folder requires the folder to exist, otherwise the error "invalid path" will be generated.

So, how can you monitor file changes if the file or folder does not exist? What’s more troublesome is how can you monitor it if many top-level folders don’t exist? This article will tell you the method.

The code in this article is suitable for .NET Framework and .NET Core, and does not require any third-party dependencies.


Method 1: Create a folder (to avoid the problem, but it is also a solution)

If the folder does not exist, just create it and you can monitor it! This is actually evading the problem. But I wrote it out because if I don't say it, the original simple problems of some friends may become complicated.

public void Watch(string file ) { path = Path .GetFullPath( file ); var directory = Path .GetDirectoryName( path ); var file = Path .GetFileName( path ); //If the folder does not exist, create the folder. if (! Directory .Exists( directory )) { Directory .CreateDirectory( directory ); } //Monitor the changes of file files in the directory folder var watcher = new FileSystemWatcher( directory , file ) { EnableRaisingEvents = true, NotifyFilter = NotifyFilters . LastWrite , }; watcher . Changed += FinalFile_Changed ; //use watcher to do other things . } private void FinalFile_Changed(object sender , FileSystemEventArgs e ) { //When the file is changed, the code here will be executed. }

The meaning of the above code is:

  1. Take out the file path and divide it into a folder part and a file part;
  2. Determine whether the folder exists, if it does not exist, create the folder;
  3. Watch for changes to this file in the folder.

It should be noted,

FileSystemWatcher
Originally it is a monitoring folder, the first parameter is the path of the monitored folder, and the second parameter is the filtering wildcard of the monitored file or folder.

However, the official documentation states:

To watch a specific file, set the Filter property to the file name. For example, to watch for changes in the file MyDoc.txt, set the Filter property to “MyDoc.txt”.

If you need to monitor a specific file, then directly set the following filter to the file name, then the corresponding file will be directly monitored.

If you always want to create this file in your business, creating this folder at the beginning can avoid a lot of trouble. This is why I put this method here as the preferred method. Although this is actually to avoid the problem, it is really a good way.

Method 2: Recursively monitor folders

This method is suitable for situations where you cannot create a file or folder if it does not exist. Maybe it is your business need, maybe because you are writing a library. As the most common business, the library does not want to change the user's environment.

At this time, the idea we can consider is to monitor files or folders recursively .

For example, we have this folder structure:

C:\a\b\x.txt

Hope to monitor the changes of x.txt.

Then, if the b folder does not exist, then the a folder is monitored, and if the a folder does not exist, then the C: drive is monitored. In fact, we don't need to think about the situation that the C: drive doesn't exist anymore (when you really encounter it, consider business evasion...).

Code

Since we need to monitor recursively, we need to find out which layer we need to go to when we monitor for the first time.

Here, we can use a

while
Do it in a loop, looking for folders layer by layer. Until you can find a layer, the folder exists but the subfolder does not exist. At this time we can monitor the creation of subfolders.

I wrote a function to return the folder that exists at this time, and the subfolder or file that does not exist.

Of course, there are special cases, that is, when the file already exists directly, the folder where the file is located and the file name are also returned.

private (string directory , string file ) FindWatchableLevel() { var path = _file . FullName ; //If the file exists, return the folder where the file is located and the file itself. if ( File .Exists( path )) { return ( Path .GetDirectoryName( path ), Path .GetFileName( path )); } //If the file does not exist, but the folder exists, the folder and the file itself are also returned. //This is reflected in the first layer of loop below. //For each layer loop. while (true) { var directory = Path .GetDirectoryName( path ); var file = Path .GetFileName( path ); //Check if the folder exists, as long as the folder exists, then you can return. if ( Directory .Exists( directory )) { return ( directory , file ); } //If even the folder does not exist, then you need to find the upper folder. path = directory ; } }

Next, according to the obtained folder and file, determine whether it exists or not, and decide whether to monitor the change of the file or the change of the file/folder structure. If the structure of the file/folder changes, you need to call this method again to find the folder that should be monitored.

public void Watch() { var ( directory , file ) = FindWatchableLevel(); if ( File .Exists( _file . FullName )) { //If the file exists, it means this is the final file. //Note that File.Exists will return false when judging an existing folder with the same name. _watcher = new FileSystemWatcher( directory , file ) { EnableRaisingEvents = true, NotifyFilter = NotifyFilters . LastWrite , }; _watcher . Changed += FinalFile_Changed ; _watcher . Deleted += FileOrDirectory_CreatedOrDeleted ; } else { //Note that the file here may be a file or a folder. _watcher = new FileSystemWatcher( directory , file ) { EnableRaisingEvents = true, }; _watcher . Created += FileOrDirectory_CreatedOrDeleted ; _watcher . Renamed += FileOrDirectory_CreatedOrDeleted ; _watcher . Deleted += FileOrDirectory_CreatedOrDeleted ; } }

We passed

File.Exists(_file.FullName)
To determine whether the final file exists, and to distinguish whether it is monitoring the final file change or the change of the folder structure.

private void FileOrDirectory_CreatedOrDeleted(object sender , FileSystemEventArgs e ) { //When the file/folder structure changes, re-monitor. _watcher ?.Dispose(); Watch(); } private void FinalFile_Changed(object sender , FileSystemEventArgs e ) { //This is where the final file changed. }

Complete code and usage

Because the code is still a little bit more. If you put it in your original business, it will really pollute your business code. So I encapsulated a class

FileWatcher
. It can be used without relying on anything, and you can copy it to your project.

You can read the code at the end of this article, or go to the gist to view: FileWatcher that helps you to watch a single file change even if the file or it's owner folders does not exists ..

Use method and

FileSystemWatcher
Similar, but simpler:

_watcher = new FileWatcher(@"C:\Users\walterlv\Desktop\demo.txt"); _watcher . Changed += OnFileChanged ; _watcher .Watch();
private void OnFileChanged(object sender , EventArgs e ) { //The purest file change event is triggered only when the content of the file really changes. }

Features, advantages and disadvantages of this method

In fact,

FileSystemWatcher
The surveillance is also somewhat hollow. If you only monitor the first-level folder instead of recursively monitoring the sub-folders (by setting
IncludeSubdirectories
Attribute to specify), then there will be some situations that cannot be monitored. However, if you really monitor subfolders recursively, you will hear a lot of events that need to be filtered.

So what are the supported and unsupported situations for this method?

Still assume that the monitored file is: C:\a\b\x.txt .

Support these situations:

  1. The file x.txt does not exist at the beginning, and then it is created.
  2. At first, b\x.txt did not exist, and then they were created one by one.
  3. Rename the file from y.txt to x.txt.
  4. The file x.txt exists at the beginning, then it is deleted, and then re-created.

These situations are not supported:

  1. The file exists at the beginning, but you directly delete the a or b folder instead of deleting x.txt first.
  2. The file exists at the beginning, but directly move b\x.txt along with the file and folder, and then delete the file or folder.
  3. At first, b\x.txt did not exist, but now the folder structure is maintained and the files and folders are moved into the a folder.

Of course, there are also some unexpected findings:

  1. The file exists at the beginning, but if you directly move b\x.txt along with the file and folder, you can still monitor the change of the x.txt file, but it is no longer in the original directory.

Attach all source code

If you don’t see it, please visit: FileWatcher that helps you to watch a single file change even if the file or it's owner folers does not exists ..


Reference


My blog will first be published at https://walterlv.com/ , and CSDN and blog garden will only select and publish from it, and once it is published, it will not be updated.

If you see anything you don’t understand on the blog, please share with us. I built the dotnet vocational and technical college. Welcome everyone to join.

View Image

This work is licensed under the Creative Commons Attribution-Non-Commercial Use-Share 4.0 International License Agreement in the same way . Welcome to reprint, use, and republish, but be sure to keep the article's signature Lu Yi (including link: https://blog.csdn.net/wpwalter ), and it must not be used for commercial purposes. The modified works based on this article must be published with the same license . If you have any questions, please contact me.


Reference : https://blog.csdn.net/WPwalter/article/details/85526337