C# 如何在后台运行时监视文件夹中的文件并将所述文件移动到另一个文件夹?

C# 如何在后台运行时监视文件夹中的文件并将所述文件移动到另一个文件夹?,c#,filesystemwatcher,movefile,C#,Filesystemwatcher,Movefile,我想要一个程序,将不断监测一个文件夹的文件,当一个文件出现在所说的文件夹中的程序应该等待该文件是可访问的,然后移动到另一个文件夹所说的文件。目前,文件未从文件夹“test”移动到“test2” 我这样做是为了,当我点击开始按钮时,表单最小化,并在后台运行,不断监视文件夹 private void btstart_Click(object sender, EventArgs e) { this.WindowState = FormWindowState.Mi

我想要一个程序,将不断监测一个文件夹的文件,当一个文件出现在所说的文件夹中的程序应该等待该文件是可访问的,然后移动到另一个文件夹所说的文件。目前,文件未从文件夹“test”移动到“test2”

我这样做是为了,当我点击开始按钮时,表单最小化,并在后台运行,不断监视文件夹

private void btstart_Click(object sender, EventArgs e)
        {
            this.WindowState = FormWindowState.Minimized;

            FileSystemWatcher watcher = new FileSystemWatcher();
            watcher.Path = @"C:\test";
            watcher.NotifyFilter = NotifyFilters.LastWrite;



            watcher.Created += new FileSystemEventHandler(watcher_FileCreated);
            watcher.EnableRaisingEvents = true;
        }

        public static bool Ready(string filename)
        {
            try
            {
                using (FileStream inputStream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.None))
                    return inputStream.Length > 0;
            }
            catch (Exception)
            {
                return false;
            }
        }
        void watcher_FileCreated(object sender, FileSystemEventArgs e)
        {
            string path1 = @"C:\test";
            string path2 = @"C:\test2";
            string files = @"*.*"; 
            string[] fileList = Directory.GetFiles(path1, files);
            foreach (string file in fileList)
            {
                if (Ready(file) == true)
                {
                    File.Move(path1, path2);
                }
            }
        }
表面上看,这并不明显,但实际情况是,文件没有从文件夹“test”移动到文件夹“test2”,没有引发异常,没有错误,文件没有被任何人使用,也没有打开,权限也都设置正确,文件很简单,没有被移动

编辑解决方案:由于此线程中发布的答案,代码现在可以工作了。 我自己添加了一些东西,以便处理重复的异常

folderlocationpath&folderdestinationpath变量是通过FolderBrowser对话框读取的,因此用户可以自己选择这两个文件夹位置 这就是我目前拥有的:

string path1 = folderlocationpath;
            string path2 = folderdestinationpath;
            string files = @"*.*";
            string[] fileList = Directory.GetFiles(path1, files);
            foreach (string file in fileList)
            {
                if (Ready(file) == true)
                    try
                    {
                        File.Move(file, Path.Combine(path2, Path.GetFileName(file)));
                    }
                    catch (IOException) // for duplicate files an exception that deletes the file in destination folder and then moves the file from origin folder
                    {
                        string files2 = Path.GetFileName(file);
                        string[] fileList2 = Directory.GetFiles(path2, files2);
                        foreach (string file2 in fileList2)
                            File.Delete(file2);

                        File.Move(file, Path.Combine(path2, Path.GetFileName(file)));
                    }
            }

答案显而易见。。将文件夹路径传递给文件。移入文件输入和文件输出路径

File.Move(文件,路径2+“\”+System.IO.Path.GetFileName(文件))


在正文中添加了1个字符

我考虑过对@BanMe answer进行编辑,但似乎在响应中更全面一点会更好,因为在我自己测试之后,我将有效地为他的建议修复添加一个额外的更改(实际上,这非常重要)

这已经过测试,验证在我的系统上运行。为了让它更有效地工作,我还需要做一个额外的改变。它包含了对
Move
命令
Path.Combine
的修复,但更重要的是,它还向
文件名添加了一个
NotifyFilter

您应该能够部署代码的这一部分,并且它应该按照我的测试预期工作

private void btstart_Click(object sender, EventArgs e)
{
    this.WindowState = FormWindowState.Minimized;
    FileSystemWatcher watcher = new FileSystemWatcher();
    watcher.Path = @"C:\test";
    watcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.FileName;
    watcher.Created += new FileSystemEventHandler(watcher_FileCreated);
    watcher.EnableRaisingEvents = true;
}

public static bool Ready(string filename)
{
    try
    {
        using (FileStream inputStream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.None))
            return inputStream.Length > 0;
    }
    catch (Exception)
    {
        return false;
    }
}

void watcher_FileCreated(object sender, FileSystemEventArgs e)
{
    string path1 = @"C:\test";
    string path2 = @"C:\test2";
    string files = @"*.*";
    string[] fileList = Directory.GetFiles(path1, files);
    foreach (string file in fileList)
    {
        if (Ready(file) == true)
        {
            File.Move(file, Path.Combine(path2, System.IO.Path.GetFileName(file)));
        }
    }
}
为什么我们需要展开
NotifyFilters
?看一看,我将在这里总结相关部分:

我也有这种行为的问题。如果您仔细阅读代码(并且查看MSDN文档),您会发现 NotifyFilter以默认值开始:

NotifyFilters.FileName | NotifyFilters.DirectoryName | NotifyFilters.LastWrite

因此,当您说.NotifyFilter=NotifyFilters.CreationTime时,您正在删除这些其他值,这解释了 行为。我不知道为什么NotifyFilters.CreationTime无法捕获 新文件…似乎应该,不是吗

您将
NotifyFilter
隔离为仅
LastWrite
似乎忽略了
FileSystemWatcher
的其他方面。添加
FileName
为我解决了这个问题


如果文件已经存在于
C:\TEST2\
文件夹中,您可能仍然会遇到异常,但这是在
文件之前要做的一个非常简单的调整。如果必须移动

“它就是不存在”-阅读并调试您的代码,您的问题包括实际观察到的行为。最有可能的是文件仍在使用,并且您的代码引发了一个异常-您忽略了该异常。那么,您是否尝试过调试您的应用程序?方法是“什么都没有发生”我认为很明显,假设文件没有被移动,也没有被使用,因为我一直都在测试文件夹中的文件。没有异常,没有错误,文件只是没有移动。没有错误?您正在静默地捕获并忽略异常!至少,记录一些内容。我尝试放置一个debug指向许多位置,它只是从一开始就没有引发事件,但现在它不再重要了,因为它是创建完整路径名的首选方法。不起作用,文件夹“test”中的文件不会移动到文件夹“test2”并没有抛出异常,也并没有错误,只是并没有创建文件moved@JohnLinaer无论哪种方式,该特定行也不正确。您正在指示系统将
移动到
C:\TEST到C:\TEST2-根本不指定任何文件名(在收集的文件列表中枚举时,这将是
file
)。如果文件已经存在于TEST2中,并且稍后在测试中再次出现,您也会遇到异常。这是有道理的,感谢您指出,我甚至没有考虑过。但它似乎仍然不起作用,首先,不允许直接写入“\”,但即使我生成字符串a=@“\”;并将path2+a+Path.GetFileName(文件)放入,但仍不会移动文件字符串转义“\\”。另一个注意事项:由于您筛选文件的方式,任何没有扩展名的文件都不会被移动。非常感谢您的帮助和解释,很抱歉我之前无法查看此内容,因为还有很多其他项目正在进行。经过一段时间的测试,我发现文件确实正在移动,但只有在文件被送入文件夹“test”,而该程序在后台运行。然而,似乎有时文件在复制后会拒绝移动,就像我向其馈送文件的1/3次一样,我认为我可能馈送文件太快了,因为它不会为文件夹中已经存在的文件引发事件,所以当我向另一个文件馈送文件时,它只会移动文件。因此,我所做的只是复制文件来自watcher_FileCreated方法的代码,并将其放在FileSystemWatcher()之前,因此,当我单击“开始”让程序在后台运行时,它将首先移动文件夹中已有的文件,然后开始监视在文件夹中创建的新文件。现在,我只需要弄清楚如何使其在发现重复文件时替换文件。如果目标已存在,请考虑如何移动文件,或者编写新文件s