C# FileSystemWatcher 复制文件夹完成

C# FileSystemWatcher Copy folder complete

我正在使用 FileSystemWatcher 来监视将用于执行某些文件重命名的文件夹。
唯一要复制的是包含文件的文件夹。不会有单个文件放入受监控的文件夹中。这是设置 FileSystemWatcher

的代码
watcher.Path = path;
watcher.NotifyFilter = NotifyFilters.DirectoryName | NotifyFilters.FileName;
watcher.IncludeSubdirectories = true;
watcher.Filter = "*.*";
watcher.Created += new FileSystemEventHandler(watcher_Created);
watcher.Changed += new FileSystemEventHandler(watcher_Changed);
watcher.Renamed += new RenamedEventHandler(watcher_Renamed);
watcher.EnableRaisingEvents = true; 

此设置似乎没有任何问题..

复制的文件夹大小可以在 50-200mb 之间。有没有办法 check/make 在开始重命名过程之前确保所有文件都已完成复制。 我试过这个想法,如果在调用 GetFiles() 时复制仍在发生,我会得到一个 IOException。

bool finishedCopying = false;
while (!finishedCopying)
{
    try
    {
        List<FileInfo> fileList = directoryInfo.GetFiles().ToList();
        AlbumSearch newAlbum = new AlbumSearch(directoryInfo);
        return newAlbum;
    }
    catch (IOException)
    {
        finishedCopying = false;
    }
}

如果需要更多信息,请询问我是否可以提供。

Ta.

这是一个小型演示应用程序,它首先检查文件,然后使用两个哈希集来跟踪复制的文件。这仅在源目录已知时才有效。无法知道文件是从文件副本创建还是直接创建,因此您只能将两个已知目录与 Directory.GetFiles 进行比较。而且,正如评论中所说,您仍然需要检查在复制过程中是否在旧目录中添加/删除/重命名了其他文件

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
    class Program
    {
        static HashSet<string> oldDirFiles = new HashSet<string>();
        static HashSet<string> newDirFiles = new HashSet<string>();

        static string oldDir = "C:\New Folder";
        static string newDir = "C:\New Folder 2";

        static System.Threading.ManualResetEvent resetEvent = new System.Threading.ManualResetEvent(false);

        static void Main(string[] args)
        {
            System.IO.FileSystemWatcher watcher = new System.IO.FileSystemWatcher();
            watcher.Path = newDir;
            watcher.NotifyFilter = NotifyFilters.DirectoryName | NotifyFilters.FileName;
            watcher.IncludeSubdirectories = true;
            watcher.Filter = "*.*";
            watcher.Created += watcher_Created;
            watcher.Changed += watcher_Changed;
            watcher.Renamed += watcher_Renamed;
            watcher.EnableRaisingEvents = true;

            //get all files in old directory
            var oldFiles = Directory.GetFiles(oldDir, "*.*", SearchOption.AllDirectories);
            foreach (var file in oldFiles)
                oldDirFiles.Add(file);

            resetEvent.WaitOne();

            //now launch the directory copy

            //then you have to check if in the meaning time, new files were added or renamed
            //that could be done also with a watcher in the old directory
        }

        static void watcher_Renamed(object sender, RenamedEventArgs e)
        {
            throw new NotImplementedException();
        }

        static void watcher_Changed(object sender, FileSystemEventArgs e)
        {
            throw new NotImplementedException();
        }

        static void watcher_Created(object sender, FileSystemEventArgs e)
        {
            //check if the copied file was in the old directory before starting
            if (oldDirFiles.Contains(e.FullPath.Replace(newDir, oldDir)))
            {
                newDirFiles.Add(e.FullPath);
                //if all the files have been copied, the file count will be the same in the two hashsets
                //the resetevent.Set() signal the waiting thread and the program can proceed
                if (newDirFiles.Count == oldDirFiles.Count)
                    resetEvent.Set();
            }
        }
    }
}

我使用计时器试了一下。它可能不是目前最漂亮的解决方案,但在第一次测试时它似乎到目前为止有效。本质上,当一个文件夹被复制到受监视的文件夹时,它会将文件夹路径添加到 AlbumList。该文件夹中的文件将触发 Created 事件。这等待文件完成复制。一旦完成,它就会启动一个计时器。如果触发了新的 Created 事件,计时器将自行重置。

当 timer.elapsed 事件被触发时,它假设(我知道假设是所有 f*&k ups 之母)没有更多的文件要复制并且可以开始处理完全复制的文件夹..

System.Timers.Timer eventTimer = new System.Timers.Timer(); 
List<string> AlbumList = new List<string>();

private void watcher_Created(object sender, FileSystemEventArgs e)
{    
    if (Directory.Exists(e.FullPath))
    {
        AlbumList.Add(e.FullPath);
    }

    if (File.Exists(e.FullPath))
    {
        eventTimer.Stop();
        FileInfo newTrack = new FileInfo(e.FullPath);
        while (IsFileLocked(newTrack))
        {
            // File is locked. Do Nothing..
        }
        eventTimer.Start();              
    }
}

private void eventTimer_Elapsed(object sender, ElapsedEventArgs e)
{
    List<string> ItemToRemove = new List<string>();
    foreach (var item in AlbumList)
    {            
        DirectoryInfo di = new DirectoryInfo(item);
        AlbumSearch newAlbum = new AlbumSearch(di);

        if (DoSomethingMethod(newAlbum))
        {
            ItemToRemove.Add(item);
        }
        else
        {
            // why did it fail
        }
    }

    foreach (var path in ItemToRemove)
    {
        AlbumList.Remove(path);
    }
}

private bool DoSomethingMethod(AlbumSearch as)
{
    // Do stuff here 
    return true;
}