c# - 创建完成后监视文件夹并复制新文件
问题描述
我构建了一个控制台应用程序,用于监控 Windows 2019 服务器上的一组文件夹,并使用相同的文件名将任何新创建的 .txt 文件复制到另一个文件夹。到目前为止,它适用于基本功能。现在我必须处理这样一个事实,即大多数情况下,这些文件很大,需要几分钟才能完成创建。我浏览了几篇 SO 帖子并拼凑了以下代码来尝试完成此操作:
using System;
using System.IO;
namespace Folderwatch
{
class Program
{
static void Main(string[] args)
{
string sourcePath = @"C:\Users\me\Documents\SomeFolder";
FileSystemWatcher watcher = new FileSystemWatcher(sourcePath);
watcher.EnableRaisingEvents = true;
watcher.IncludeSubdirectories = true;
watcher.Filter = "*.txt";
// Add event handlers.
watcher.Created += new FileSystemEventHandler(OnCreated);
}
// Define the event handlers.
private static void OnCreated(object source, FileSystemEventArgs e)
{
// Specify what is done when a file is created.
FileInfo file = new FileInfo(e.FullPath);
string wctPath = e.FullPath;
string wctName = e.Name;
string createdFile = Path.GetFileName(wctName);
string destPath = @"C:\Users\SomeOtherFolder";
string sourceFile = wctPath;
string destFile = Path.Combine(destPath, createdFile);
WaitForFile(file);
File.Copy(sourceFile, destFile, true);
}
public static bool IsFileLocked(FileInfo file)
{
try
{
using (FileStream stream = file.Open(FileMode.Open, FileAccess.Read, FileShare.None))
{
stream.Close();
}
}
catch (IOException)
{
//the file is unavailable because it is:
//still being written to
//or being processed by another thread
//or does not exist (has already been processed)
return true;
}
//file is not locked
return false;
}
public static void WaitForFile(FileInfo filename)
{
//This will lock the execution until the file is ready
//TODO: Add some logic to make it async and cancelable
while (!IsFileLocked(filename)) { }
}
}
}
我在该OnCreated
方法中尝试做的是检查并等待文件创建完成,然后将文件复制到另一个目的地。我似乎不知道我在用该WaitForFile(file)
行做什么 - 如果我注释掉该行并且文件创建是即时的,则文件会按预期复制。如果我使用这WaitForFile
条线,什么都不会发生。我从 SO 上的其他帖子中获取了IsFileLocked
andWaitForFile
方法,但我显然没有正确实施它们。
我已经注意到这个 Powershell 版本Copy File On Creation (一旦完成),我不确定这里的答案是否可以为我指明正确的方向 b/c 我对 PS 的了解甚至比对 C# 的了解还要少。
编辑#1:我应该在接受答案之前测试更长的时间 - 我认为我们已经接近但在程序运行大约一分钟后,我在程序崩溃之前收到以下错误:
未处理的异常。System.IO.IOException:该进程无法访问文件“C:\Users\me\Dropbox\test1.log”,因为它正被另一个进程使用。在 System.IO.FileSystem.CopyFile(String sourceFullPath, String destFullPath, Boolean overwrite) 在 Folderwatch.Program.OnCreated(Object source, FileSystemEventArgs e) 在 C:\Users\me\OneDrive - Development\Source\repos\FolderWatchCG\FolderWatchCG \Program.cs:System.Threading.Tasks.Task.<>c.b__139_1(Object state) 的第 61 行,System.Threading.QueueUserWorkItemCallbackDefaultContext.Execute()
的 System.Threading.ThreadPoolWorkQueue.Dispatch() 的 System.Threading。 _ThreadPoolWaitCallback.PerformWaitCallback()
对此的任何建议将不胜感激。当我进一步分析这些文件夹中的文件时,其中一些是实时写入的日志文件,因此可能是文件在实际完成之前被写入了数小时。我想知道其中一个是否在NotifyFilter
这里发挥作用?
解决方案
该方法有一个错误WaitForFile()
,即它当前在文件未锁定时等待(而不是相反)。除此之外,您还需要一种方法来确认该文件确实存在。实现此目的的一种简单方法是将方法更改WaitForFile()
为如下所示:
public static bool WaitForFile(FileInfo file)
{
while (IsFileLocked(file))
{
// The file is inaccessible. Let's check if it exists.
if (!file.Exists) return false;
}
// The file is accessible now.
return true;
}
只要文件存在并且无法访问,这将一直等待。
然后,您可以按如下方式使用它:
bool fileAvailable = WaitForFile(file);
if (fileAvailable)
{
File.Copy(sourceFile, destFile, true);
}
但是这种方法的问题是while
循环使线程保持忙碌,这 a) 消耗了大量的 CPU 资源,并且 b) 阻止程序处理其他文件,直到它完成等待那个文件。因此,在每次检查之间使用异步等待可能会更好。
将方法更改WaitForFile
为:
public static async Task<bool> WaitForFile(FileInfo file)
{
while (IsFileLocked(file))
{
// The file is inaccessible. Let's check if it exists.
if (!file.Exists) return false;
await Task.Delay(100);
}
// The file is accessible now.
return true;
}
然后,像这样在里面等待它OnCreated
:
private async static void OnCreated(object source, FileSystemEventArgs e)
{
// ...
bool fileAvailable = await WaitForFile(file);
if (fileAvailable)
{
File.Copy(sourceFile, destFile, true);
}
}
推荐阅读
- python - 合并列的重复单元格
- javascript - How to fix ' "X" is not defined no-undef' error in React.js
- javascript - How to redirect automatically php js
- python - 如何比较两个 DF 中的两列,保持一些列常量并打印行?
- javascript - Javascript returning in forEach loop
- php - 即使该语句为图像标题返回 true,条件语句也不起作用
- java - 数组操作:HackerRank 问题:JAVA
- flutter - 颤振不应该根据设计缩小或放大图像和文本吗?为什么我看到了很大的不同?
- javascript - 如何从作为模块导出的请求中获取回调函数的返回值
- java - Office 365 使用 Java SDK 与图形 API 集成的问题