我正在用c#编写一个WPF应用程序,我需要移动一些文件 - 我真的需要知道文件是否成功。为此,我编写了一个检查,确保文件在移动后到达目标目录 - 问题是有时我会在文件完成移动之前进行检查:
System.IO.File.Move(file.FullName, endLocationWithFile);
System.IO.FileInfo[] filesInDirectory = endLocation.GetFiles();
foreach (System.IO.FileInfo temp in filesInDirectory)
{
if (temp.Name == shortFileName)
{
return true;
}
}
// The file we sent over has not gotten to the correct directory....something went wrong!
throw new IOException("File did not reach destination");
}
catch (Exception e)
{
//Something went wrong, return a fail;
logger.writeErrorLog(e);
return false;
}
有人可以告诉我如何确保文件实际到达目的地吗? - 我将要移动的文件可能非常大 - (全高清mp4文件长达2小时)
谢谢!
答案 0 :(得分:8)
您可以使用Aysnc
Await
的流来确保文件完全复制
这样的事情应该有效:
private void Button_Click(object sender, RoutedEventArgs e)
{
string sourceFile = @"\\HOMESERVER\Development Backup\Software\Microsoft\en_expression_studio_4_premium_x86_dvd_537029.iso";
string destinationFile = "G:\\en_expression_studio_4_premium_x86_dvd_537029.iso";
MoveFile(sourceFile, destinationFile);
}
private async void MoveFile(string sourceFile, string destinationFile)
{
try
{
using (FileStream sourceStream = File.Open(sourceFile, FileMode.Open))
{
using (FileStream destinationStream = File.Create(destinationFile))
{
await sourceStream.CopyToAsync(destinationStream);
if (MessageBox.Show("I made it in one piece :), would you like to delete me from the original file?", "Done", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
{
sourceStream.Close();
File.Delete(sourceFile);
}
}
}
}
catch (IOException ioex)
{
MessageBox.Show("An IOException occured during move, " + ioex.Message);
}
catch (Exception ex)
{
MessageBox.Show("An Exception occured during move, " + ex.Message);
}
}
如果您使用VS2010,则必须安装Async CTP才能使用新的Async / Await语法
答案 1 :(得分:1)
您可以观察文件从原始目录中消失,然后确认它们确实出现在目标目录中。
我对文件观察者没有很好的经验。我可能会让线程执行移动等待AutoResetEvent,而单独的线程或计时器运行以定期检查文件是否从原始位置消失,检查它们是否在新位置,并且可能(取决于根据您的环境和需求)对文件执行一致性检查(例如,MD5检查)。一旦满足这些条件,“checker”线程/计时器将触发AutoResetEvent,以便原始线程可以进行。
在“检查器”中加入一些“这是太长时间”的逻辑。
答案 2 :(得分:1)
为什么不通过复制流来管理自己的副本?
//http://www.dotnetthoughts.net/writing_file_with_non_cache_mode_in_c/
const FileOptions FILE_FLAG_NO_BUFFERING = (FileOptions) 0x20000000;
//experiment with different buffer sizes for optimal speed
var bufLength = 4096;
using(var outFile =
new FileStream(
destPath,
FileMode.Create,
FileAccess.Write,
FileShare.None,
bufLength,
FileOptions.WriteThrough | FILE_FLAG_NO_BUFFERING))
using(var inFile = File.OpenRead(srcPath))
{
//either
//inFile.CopyTo(outFile);
//or
var fileSizeInBytes = inFile.Length;
var buf = new byte[bufLength];
long totalCopied = 0L;
int amtRead;
while((amtRead = inFile.Read(buf,0,bufLength)) > 0)
{
outFile.Write(buf,0,amtRead);
totalCopied += amtRead;
double progressPct =
Convert.ToDouble(totalCopied) * 100d / fileSizeInBytes;
progressPct.Dump();
}
}
//file is written
答案 3 :(得分:0)
您很可能希望移动发生在一个单独的线程中,这样您就不会在几个小时内停止执行您的应用程序。
如果程序无法在没有完成移动的情况下继续,那么您可以打开一个对话框并定期检查移动线程以更新进度跟踪器。这为用户提供了反馈,并且可以防止他们感觉好像程序已经冻结。
这里有信息和示例: http://hintdesk.com/c-wpf-copy-files-with-progress-bar-by-copyfileex-api/
答案 4 :(得分:0)
尝试在后台任务中定期检查是否复制了文件 size达到原始文件的文件大小(您可以添加文件之间的哈希比较)
答案 5 :(得分:0)
最近遇到了类似的问题。
OnBackupStarts();
//.. do stuff
new TaskFactory().StartNew(() =>
{
OnBackupStarts()
//.. do stuff
OnBackupEnds();
});
void OnBackupEnds()
{
if (BackupChanged != null)
{
BackupChanged(this, new BackupChangedEventArgs(BackupState.Done));
}
}
不要等待,对事件做出反应