我正在研究定期需要将数据保存到磁盘的服务器软件。我需要确保旧文件被覆盖,并且在意外情况下文件不会被破坏(例如,仅部分覆盖)。
我采用了以下模式:
string tempFileName = Path.GetTempFileName();
// ...write out the data to temporary file...
MoveOrReplaceFile(tempFileName, fileName);
......其中MoveOrReplaceFile是:
public static void MoveOrReplaceFile( string source, string destination ) {
if (source == null) throw new ArgumentNullException("source");
if (destination == null) throw new ArgumentNullException("destination");
if (File.Exists(destination)) {
// File.Replace does not work across volumes
if (Path.GetPathRoot(Path.GetFullPath(source)) == Path.GetPathRoot(Path.GetFullPath(destination))) {
File.Replace(source, destination, null, true);
} else {
File.Copy(source, destination, true);
}
} else {
File.Move(source, destination);
}
}
只要服务器具有对文件的独占访问权限,这就可以正常工作。但是,File.Replace似乎对外部文件访问非常敏感。每当我的软件在具有防病毒或实时备份系统的系统上运行时,随机的File.Replace错误就会弹出:
System.IO.IOException:无法删除要替换的文件。
以下是我已消除的一些可能原因:
以下是我遇到的一些建议,以及为什么我不想使用它们:
我很感激任何关于每次都使File.Replace工作的输入,或者更一般地说,可靠地保存/覆盖磁盘上的文件。
答案 0 :(得分:26)
您确实想要使用第3个参数,即备份文件名。这允许Windows简单地重命名原始文件而不必删除它。如果任何其他进程在没有删除共享的情况下打开文件,则删除将失败,重命名绝不是问题。然后,您可以在Replace()调用后自行删除它并忽略错误。同时在Replace()调用之前将其删除,这样重命名不会失败,并且您将清除早期尝试失败。粗略地说:
string backup = destination + ".bak";
File.Delete(backup);
File.Replace(source, destination, backup, true);
try {
File.Delete(backup);
}
catch {
// optional:
filesToDeleteLater.Add(backup);
}
答案 1 :(得分:2)
有几种可能的方法,其中一些是:
当然,所有3种方法都有其自身的缺点和优点
答案 2 :(得分:1)
如果软件正在写入NTFS分区,请尝试使用Transactional NTFS。您可以使用AlphFS作为API的.NET包装器。这可能是编写文件和防止腐败的最可靠方式。