c# - 在繁忙的环境中可靠地保存文件 (File.Replace)

标签 c# .net windows filesystems

我正在开发需要定期将数据保存到磁盘的服务器软件。我需要确保覆盖旧文件,并且在意外情况下文件不会损坏(例如,仅部分覆盖)。

我采用了以下模式:

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: Unable to remove the file to be replaced.

以下是我排除的一些可能原因:

  • 未释放的文件句柄:using() 确保尽快释放所有文件句柄。
  • 线程问题:lock() 保护对每个文件的所有访问。
  • 不同的磁盘卷:File.Replace() 在跨磁盘卷使用时失败。我的方法已经对此进行了检查,然后回退到 File.Copy()。

下面是我遇到的一些建议,以及我不想使用它们的原因:

  • Volume Shadow Copy Service:这仅在有问题的第三方软件(备份和防病毒监视器等)也使用 VSS 时才有效。使用 VSS 需要大量的 P/Invoke,并且存在特定于平台的问题。
  • 锁定文件:在 C# 中,锁定文件需要保持 FileStream 处于打开状态。它会将第三方软件拒之门外,但 1) 我仍然无法使用 File.Replace 替换文件,以及 2) 就像我上面提到的,我宁愿先写入一个临时文件,以避免意外腐败。

对于让 File.Replace 每次都能工作,或者更一般地说,可靠地保存/覆盖磁盘上的文件的任何意见,我将不胜感激。

最佳答案

真的想使用第三个参数,即备份文件名。这使 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);
}

关于c# - 在繁忙的环境中可靠地保存文件 (File.Replace),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8958094/

相关文章:

c# - .NET 示例 VCF 阅读器

.net - ASP.NET身份验证两个因素不起作用-Cookie问题?

c++ - wcswidth_l 的 Windows 版本

c# - 我将如何在设计时设置我的 UserControl 的标签?

c# - 将对象标记为可序列化会产生开销吗?

c# - 用于在 C# 中的 .vdproj 文件中查找和替换任何产品名称值的 .NET 正则表达式

windows - TRichEdit 和 URL 高亮问题

c# - 获取Python可执行文件路径

c# - 如何向上传到 Amazon S3 的图像添加 Cache-Control HTTP header ?

c# - 得到一个错误,可能是WebResource.axd