C# - 仅当文件完全复制到磁盘时才复制文件
Posted
技术标签:
【中文标题】C# - 仅当文件完全复制到磁盘时才复制文件【英文标题】:C# - Only copy file when it has been completely copied to disk 【发布时间】:2020-02-29 07:11:35 【问题描述】:我正在编写一个等待将文件复制到文件夹的应用程序,当文件被复制后,我会尝试打开该文件。
我遇到了文件长度有时为零的问题。我相信这是因为文件没有完全完成复制到磁盘。
我已经按照https://***.com/a/937558/5330854 解决方案检查文件是否被锁定,但这仍然允许我打开长度为零的文件(我假设如果正在将文件复制到磁盘,那么当文件不为零时,这将被锁定,我将无法打开它)。
知道如何检查文件是否已完成复制到磁盘吗?
while (stream == null && IsWithingTimeCap(startTime))
stream = GetFileStream(fileInfo);
if (stream == null)
Thread.Sleep(5000);
if (fileInfo.Length == 0)
//log
private static Stream GetFileStream(IFileInfo fileInfo)
Stream stream = null;
try
stream = fileInfo.Open(FileMode.Open, FileAccess.Read, FileShare.None);
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 null;
return stream;
【问题讨论】:
感谢您抽出宝贵时间分享您的问题。但是您的问题中缺少一些东西。你的目标和困难是什么?到目前为止你做了什么?请尝试更好地解释您的问题、您的开发环境和数据结构,并分享更多代码(无截图)、一些示例、屏幕图像或草图以及用户故事或场景图。为了帮助您改进您的要求,请阅读右上角的 How do I ask a good question 和 我避免提出的问题。 您如何等待要复制的文件?文件系统观察者?什么是 fileInfo 以及如何以及何时获得它?可以多放点代码和场景顺序吗? 【参考方案1】:A. FileSystemWatcher
FileSystemWatcher
您可以使用FileSystemWatcher Class 订阅对目标目录的更改。
但是,我不知道复制完成时您可以可靠地订阅的事件。 (另请注意,Copy 方法在最后一个事件之后返回,但这可能没问题)。
这是一个例子。
var fileName = "a.zip";
var src = "c:\\tmp\\src";
var dst = "c:\\tmp\\dst";
using (FileSystemWatcher watcher = new FileSystemWatcher())
watcher.Path = dst;
void OnChanged(object source, FileSystemEventArgs e) =>
Console.WriteLine($"DateTime.Now:O, OnChanged, file: e.FullPath e.ChangeType, size: new System.IO.FileInfo(Path.Combine(dst,fileName)).Length");
void OnCreated(object source, FileSystemEventArgs e) =>
Console.WriteLine($"DateTime.Now:O, OnCreated, file: e.FullPath e.ChangeType, size: new System.IO.FileInfo(Path.Combine(dst,fileName)).Length");
watcher.NotifyFilter = NotifyFilters.Size
| NotifyFilters.DirectoryName
| NotifyFilters.Attributes
| NotifyFilters.Size
| NotifyFilters.LastWrite
| NotifyFilters.LastAccess
| NotifyFilters.CreationTime
| NotifyFilters.Security
;
watcher.Changed += OnChanged;
watcher.Created += OnCreated;
// Begin watching.
watcher.EnableRaisingEvents = true;
Console.WriteLine($"DateTime.Now:O Let's start copying");
var t = Task.Run(() =>
Console.WriteLine($"DateTime.Now:O Copy start");
System.IO.File.Copy(Path.Combine(src, fileName), Path.Combine(dst,fileName), overwrite: false);
Console.WriteLine($"DateTime.Now:O Copy end");
);
await t;
Console.ReadLine();
2019-11-04T10:54:26.4737696+10:00 Let's start copying
2019-11-04T10:54:26.4972070+10:00 Copy start
2019-11-04T10:54:26.5093223+10:00, OnChanged, file: c:\tmp\dst\a.zip Changed, size: 1232583046
2019-11-04T10:54:26.5195866+10:00, OnChanged, file: c:\tmp\dst\a.zip Changed, size: 1232583046
2019-11-04T10:54:30.6444434+10:00 Copy end
2019-11-04T10:54:30.5599570+10:00, OnChanged, file: c:\tmp\dst\a.zip Changed, size: 1232583046
B.零长度
你已经有了一个可能的答案:
我遇到了文件长度有时为零的问题。
您可以检查文件的长度并等待它不再为零。
虽然这不是严格的复制,但这里是 Firefox 下载文件期间的文件夹视图。
[![在此处输入图片描述][1]][1]
04/11/2019 10:01 <DIR> .
04/11/2019 10:01 <DIR> ..
04/11/2019 10:01 0 SSMS-Setup-ENU.exe
04/11/2019 10:01 56,512,149 SSMS-Setup-ENU.exe.part
2 File(s) 56,512,149 bytes
这是 Internet Explorer 正在下载的同一个文件。
04/11/2019 10:04 <DIR> .
04/11/2019 10:04 <DIR> ..
04/11/2019 10:04 0 SSMS-Setup-ENU.exe.pz0u92s.partial
1 File(s) 0 bytes
【讨论】:
以上是关于C# - 仅当文件完全复制到磁盘时才复制文件的主要内容,如果未能解决你的问题,请参考以下文章