我想要一个不断监视文件夹的程序,当文件出现在所述文件夹中时,程序应该等待文件可访问,然后将所述文件移动到另一个文件夹。目前,文件未从文件夹“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变量通过folderbrowserdialog读取,以便用户可以自己选择2个文件夹位置这就是我目前所拥有的:
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)));
}
}
我考虑过编写一个@BanMe答案的编辑,但似乎更好的是在响应中更具包容性,因为我实际上会为他的建议修复添加一个额外的更改(实际上,这是非常重要)经过我自己的测试。
这已经过测试,并经过验证可以在我的系统上运行。我必须进行一项额外的更改才能使其更有效地运作。它结合了对Move
命令Path.Combine
的修复,但更重要的是还将NotifyFilter
添加到FileName
。
您应该可以使用代码的这一部分,并且它应该按照我的测试预期工作。
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
?看看this answer,我将在这里总结相关部分:
我也遇到过这种行为的麻烦。如果您单步执行代码(如果您查看MSDN文档,您会发现NotifyFilter的默认值为:
NotifyFilters.FileName | NotifyFilters.DirectoryName | NotifyFilters.LastWrite
所以,当你说.NotifyFilter = NotifyFilters.CreationTime时,你正在消除那些其他值,这解释了行为的差异。我不确定为什么NotifyFilters.CreationTime没有捕获新文件......似乎应该,不应该!
看来你将NotifyFilter
隔离到LastWrite
是忽略了FileSystemWatcher
的其他方面。添加FileName
为我解决了这个问题。
如果文件已存在于C:\TEST2\
文件夹中,您可能仍会遇到异常,但如果必须,这是在File.Move
之前进行的非常简单的调整。
答案很明显..你将文件夹路径传递给File.Move中的文件和文件输出路径。
File.Move(file,path2 +“\”+ System.IO.Path.GetFileName(file));
在身体中添加了1个字符