【问题标题】:How do I rename a file over an existing file in .net without deleting the desitnation or using pinvoke?如何在不删除目标或使用 pinvoke 的情况下重命名 .net 中现有文件的文件?
【发布时间】:2016-04-30 14:59:15
【问题描述】:

我正在寻找如何在 .net 中执行简单的事务性 POSIX 样式 rename()

如果新参数命名的链接存在,则应将其删除并将旧的重命名为新的。在这种情况下,一个名为 new 的链接将在整个重命名操作期间对其他进程保持可见,并在操作开始之前引用 new 或 old 引用的文件。

在重命名要替换它的新文件之前,我不应该删除目标文件。删除然后重命名意味着新名称可能会在非零时间内返回“找不到文件”,如果此时进程或机器崩溃,情况会更糟。

关键是要实现简单的事务文件更新模式,如果我可以先成功地将替换文件写入磁盘,我只想替换文件。我真的希望对这种基本文件系统访问操作的支持不需要 pinvoke 或任何花哨的东西。我应该能够:

  1. 写一个新文件。
  2. 关闭它的FileStream 以刷新它。
  3. 在旧文件上重命名该文件(假设 FS 将在其日志的帮助下保证在文件实际刷新到硬件之前不会保留此步骤,并且此重命名操作本身是原子的)。

重命名功能隐藏在 .net 的 BCL 中的什么位置?它不在那里吗?如果不存在,是不是因为 .net 是在 Windows 9x 仍受支持的环境时编写的?还是现代 Windows 仍然不支持非特权进程的此类操作?

【问题讨论】:

    标签: .net windows io file-rename


    【解决方案1】:

    显然这只是命名的问题。在我写完这个问题并遇到this answer to another post 之前,我不知道要寻找一种名为File.Replace() 的方法。以原子方式将oldPath 的文件移动到newPath 的另一个现有文件:

    File.Replace(oldPath, newPath, null);
    

    File.Replace() 的文档中有这些有趣的花絮:

    PlatformNotSupportedException |操作系统是 Windows 98 Second Edition 或更早版本,文件系统不是 NTFS。

    如果 sourceFileName 和 destinationFileName 位于不同的卷上,此方法将引发异常。

    关于不支持非日志文件系统或 Windows 98 的注释它不能跨卷工作意味着此方法不会静默调用 File.Copy() 后跟 File.Delete() — 它不会默默地将您打算成为原子的操作转换为不安全的操作。

    但是,与rename() 不同,如果目标文件不存在,此方法将失败。但是,您可以使用 File.Move() 拒绝覆盖现有文件的事实以及 File.Replace() 可以在现有文件上以事务方式重命名某些内容以执行重命名操作的事实,尽管有时可能会失败,但至少不会离开文件处于无效状态。如果使文件保持一致状态比防止程序崩溃更重要,您可以使用:

    static void ExceptionalRename(string oldPath, string newPath)
    {
        if (File.Exists(newPath))
            File.Replace(oldPath, newPath, null);
        else
            File.Move(oldPath, newPath);
    }
    

    我希望我知道 .net 中的某些东西更像是开箱即用的 rename()。至少 File.Replace() 提供了对现有文件的事务重命名,我认为 .net 完全丢失了该文件。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-26
      • 1970-01-01
      • 1970-01-01
      • 2017-12-14
      • 1970-01-01
      • 2012-04-17
      相关资源
      最近更新 更多