简体   繁体   English

FileSystemWatcher - 识别已删除文件夹中的文件

[英]FileSystemWatcher - Recognize files in deleted folder

I have another problem with my FileSystemWatcher ;) Simply, what I want to do: 我的FileSystemWatcher有另一个问题;)简单地说,我想做什么:

I want to watch specific folders, in order to add the paths of the files to a List(Of String) and set an integer-variable for each new file. 我想观看特定的文件夹,以便将文件的路径添加到List(Of String)并为每个新文件设置整数变量。

So: 所以:

I create the file "Test.png" and it does that: 我创建文件“Test.png”,它会这样做:

(List) categoryFilesList.Add(e.FullPath)
(Integer-variable) counter += 1

Well, this is working well. 嗯,这很好用。

Now, if a file is deleted again, it should remove the path from the list and set the integer-variable down again. 现在,如果再次删除文件,它应该从列表中删除路径并再次设置整数变量。 (-= 1). ( - = 1)。

This is working well, too, but now I have a problem, I am not able to find a solution for. 这也很好,但现在我有一个问题,我无法找到解决方案。 I have IncludeSubdirectories set to true to scan the subdirectories for files. 我将IncludeSubdirectories设置为true以扫描子目录中的文件。 On adding this works fine, but on removing it does not. 在添加这个工作正常,但在删除它没有。

That is because I do NOT add folders to the list, only files. 那是因为我不向列表添加文件夹,只添加文件。 So, if I delete a folder, I am not able to know what content it was containing and how much files it were, because it is already gone. 所以,如果我删除一个文件夹,我无法知道它包含的内容和文件的数量,因为它已经消失了。

But I would want to know, how many files there were in and what their paths were to remove them again from the list and set the integer-variable down again with the amount of deleted files. 但我想知道,有多少文件以及它们的路径是从列表中再次删除它们并再次将整数变量设置为删除文件的数量。

I though about saving it anyway on changing, but I do not know how exactly and if this is a good idea. 我不管怎么说要改变它,但我不知道究竟是多少,如果这是一个好主意。 Is there a better solution? 有更好的解决方案吗?

If something is unclear, then I am sorry, ask then. 如果事情不清楚,那么我很抱歉,然后问。 I also accept C#-answers, VB.NET is just because my friend wants that. 我也接受C#-answers,VB.NET只是因为我的朋友想要的。

Thanks! 谢谢!

I am afraid that this isn't really possible to do, because of the way the deletion of a directory works in a system. 我担心这不可能做到,因为删除目录在系统中的工作方式。 The directory is deleted, but the files recursively are just part of the directory. 目录被删除,但递归的文件只是目录的一部分。

This was quite well described here on MSDN forums : 在MSDN论坛上有很好的描述:

I you observe the behavior of the trash on your desktop, you will see that each time you delete a folder, you can see that folder in the trash but you cannot see the elements within that dropped folder. 我观察桌面上垃圾桶的行为,您会看到每次删除文件夹时,您都可以在垃圾箱中看到该文件夹​​,但是您无法看到该删除文件夹中的元素。 The only way to see those elements is to recover the folder from the trash. 查看这些元素的唯一方法是从垃圾箱中恢复文件夹。

I think it happens the same thing with the FSW class. 我认为它与FSW类发生的情况相同。 When you delete a folder inside a watched directory you only have the event of the deleted folder because the folder and its contents is not really deleted but only moved to the trash. 当您删除监视目录中的文件夹时,您只有已删除文件夹的事件,因为该文件夹及其内容并未真正删除,而只是移动到废纸篓。 This is why you never receive the deleted events for the included files because they are still somewhere on your system 这就是为什么您从未收到所包含文件的已删除事件的原因,因为它们仍然在您的系统上的某个位置

According to this question here on SO , the same problem occurs when a folder is moved into the structure (and the question also shows the workaround to the moving issue). 根据SO上的这个问题 ,当文件夹移动到结构中时会出现同样的问题(问题还显示了移动问题的解决方法)。

Possible workaround for the deletion problem would be browsing the structure in advance and saving the amount of files in the directories into a tree-like structure, but it will definitely be much more complex than this. 删除问题的可能解决方法是提前浏览结构并将目录中的文件数量保存为树状结构,但它肯定会比这复杂得多。 It would look like this: 它看起来像这样:

public class DirectoryFiles
{
    public int Count {get; set;}

    public string FullPath {get; set;}
    public List<DirectoryFiles> Subdirectories {get; set; }
}

private DirectoryFiles Initialize(string fullPath)
{
    if (Directory.Exists(fullPath))
    {
        var toReturn = new DirectoryFiles { Subdirectories = new List<DirectoryFiles>() };

        foreach (string directory in Directory.GetDirectories(fullPath))
        {
            toReturn.Subdirectories.Add(this.Initialize(directory));
        }

        toReturn.Count = toReturn.Subdirectories.Sum(x => x.Count) + Directory.GetFiles(fullPath).Count();
        return toReturn;
    }
    else
    {
        throw new DirectoryNotFoundException(String.Format("Directory {0} does not exist", fullPath));
    }
}

and in the class where you are counting: 在你计算的班级里:

private int GetCountOfFiles(DirectoryFiles files, string fullPath)
{
    if (files.FullPath.Equals(fullPath, StringComparison.InvariantCultureIgnoreCase))
    {
        return files.Count;
    }
    foreach (var subdir in files.Subdirectories)
    {
        if (this.GetCountOfFiles(subdir, fullPath) != -1)
        {
            return subdir.Count;
        }
    }
    return -1;
}

This may need improvements for: 这可能需要改进:

  • Permissions - it will throw an exception if you don't have access to the files, 权限 - 如果您无权访问文件,它将抛出异常,
  • The performance is not perfect, on every subfile or subdirectory deletion you'll need to rebuild the whole structure. 性能并不完美,在每个子文件或子目录删除时,您都需要重建整个结构。 There can be some optimizations created for that as well, but should work quite well for smaller subdirectories. 也可以为此创建一些优化,但对于较小的子目录应该可以很好地工作。 If you need performance improvements, I'll leave that to you. 如果您需要改进性能,我会留给您。 For that, consider adding DirectoryFiles Parent to DirectoryFiles and recount the directories on the way up. 为此,请考虑将DirectoryFiles Parent添加到DirectoryFiles并重新计算目录。

My solution to a similar problem is as follows: Ensure your FileSystemWatcher is configured to track subfolders. 我对类似问题的解决方案如下:确保将FileSystemWatcher配置为跟踪子文件夹。 Once you do that, you should get a Delete event any time a folder or file is deleted. 一旦这样做,您应该在删除文件夹或文件时获得Delete事件。 In the case where a folder is deleted, simply iterate through your collection and remove any items that contain the path of the folder. 在删除文件夹的情况下,只需遍历您的集合并删除包含该文件夹路径的所有项目。

For example: 例如:

int numRemoved = categoryFilesList.RemoveAll(
            delegate(String s)
            {
               return s.Contains(<DeletedDirectoryPath>);
            }
            );

This would remove any items in your list which contain . 这将删除列表中包含的任何项目。 You can then use numRemoved to maintain your file count. 然后,您可以使用numRemoved来维护文件计数。 Alternatively, you could simply use the count of the list instead of maintaining your own copy of that data via the Count property on your list. 或者,您可以简单地使用列表的计数,而不是通过列表上的Count属性维护您自己的数据副本。

Additionally you should be sure that you handle the cases where items and directories are renamed so that your list of filenames is always up to date. 此外,您应该确保处理重命名项目和目录的情况,以便您的文件名列表始终是最新的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM