【问题标题】:Should I write a temp file to a temp dir? or write a temp file to the final directory?我应该将临时文件写入临时目录吗?或将临时文件写入最终目录?
【发布时间】:2010-11-10 20:32:25
【问题描述】:

当应用程序保存文件时,典型的模型是将文件保存到临时位置,然后将临时文件移动到最终位置。在某些情况下,“移动”变成了“替换”。在伪代码中:

Save temp file;
if final file exists
   delete final file;
move temp file to final filename;

那里有一个窗口,删除可能会成功,但移动可能不会成功,因此您可以通过以下方式处理:

Save temp file;
if final file exists
   move final file to parking lot
move temp file to final filename;
if move succeeded       
   delete previous final file. 
else
   restore previous final file. 

现在我的问题:

  1. 与将临时文件保存到最终目录相比,是否更倾向于将临时文件保存到临时目录,然后移动它? (如果是,为什么?)

  2. 与保存到临时文件的文件相比,首先保存到临时目录然后移动到不同目录中的最终文件的文件的属性和权限是否存在差异 在最终目录中,然后在目录中重命名?

  3. 如果对这两个问题的回答都是“是”,那么在获取文件上的相应 ACL(该文件首先保存到临时目录然后移动到最终目录)时,我该如何做首选?

【问题讨论】:

    标签: windows file permissions io acl


    【解决方案1】:

    如果只是临时文件,则在临时文件夹中创建一个临时文件。否则,在其最终目的地创建它。

    注意事项:

    1) 如果最终目的地是“拾取”文件夹,这可能不起作用(除非“拾取”进程检查锁定的文件(它应该))

    2) 最终目的地具有特殊权限,必须在代码中创建并应用才能移动到最终目的地。

    【讨论】:

      【解决方案2】:

      Microsoft Word 将临时文件保存到以波浪号 (~) 开头的原始目录。我会遵循这个约定。

      【讨论】:

      • 是的,我认为 Excel 也是如此。或许还有其他办公应用。
      • 其他应用程序会令人讨厌地破坏名称,例如 InDesign 创建的文件看起来其文件名已损坏。同样的做法,但有点不友好。
      • @Cheeso 是的,你是对的,我认为所有的办公应用程序都这样做。我认为,如果用户习惯于在打开 office 文件时看到半透明文件显示,那么当您的应用程序执行相同的操作使其成为一种安全的方法时,他们不会感到太惊讶。
      【解决方案3】:

      如果这些临时文件会变成永久文件,请在同一位置创建它们以避免必须跨磁盘/分区“移动”文件的风险,这将导致更多的 I/O(作为副本,然后一个删除)。

      如果这些是真正临时的临时文件,请在临时目录中创建(并保留它们)。

      【讨论】:

        【解决方案4】:

        您可能不想将文件写入一个目录并将其移动到另一个目录的原因是这些目录可能位于不同的文件系统上。尽管这在 Windows 上不太常见,但只要父文件系统是 ntfs,它仍然是合理的。在 unix 中,将 /tmp 设置为不同的文件系统是一种标准做法。

        这可能是一个问题的原因是因为这意味着必须将文件从一个地方复制到另一个地方。这会显着影响大文件的性能,并且肯定需要更多的搜索,即使文件很小。此外,在跨文件系统边界移动文件时,还有更多方法会导致此操作失败。当然,访问权限可能不同,但目标文件系统也可能已满,或者您现在推迟到很久以后的任何其他复杂问题。

        【讨论】:

          【解决方案5】:
          1. 最好使用 GetTempFile 例程创建临时文件,因为这会在预定义的位置(例如 C:\temp)创建临时文件,如果您的应用程序崩溃或在其中生成损坏的文件,实用程序可以删除这些临时文件。如果相同事情发生在你的最终目录中,它是不可恢复的。

          2. 是的,如果目标文件的属性或 ACL 已被编辑,属性可能会有所不同。即使您在同一文件夹中创建临时文件也可能发生这种情况。

          3. 您可以使用 File.Replace 例程来解决此问题,该例程执行一个文件与另一个文件的原子替换,将新文件的属性和 ACL 替换为旧文件。

          执行此操作的 C# 方法是对 Safe stream update of file 的回答。

          【讨论】:

          • 这很有帮助。 File.Replace 似乎正是我想要的,除了一件事:最终文件可能与 GetTempFile 返回的文件不在同一卷上。
          • 我在链接中发布的代码也处理了这种情况。
          【解决方案6】:

          我更喜欢将临时文件保存到最终目录:

          1. 它避免了您所描述的潜在权限问题。

          2. 最终目录可能位于不同的卷上,在这种情况下(将临时文件移动到最终文件)实际上是复制 + 删除 - 如果您经常这样做或如果文件很大。

          您始终可以将现有文件重命名为第二个临时文件,将新临时文件重命名为现有文件的名称,并在出错时回滚。在我看来,这是最安全的组合。

          已编辑:我看到您的“停车场”已经描述了我的建议,所以我不确定我在这里添加了多少。

          【讨论】:

            【解决方案7】:

            1 .是的,最好先保存到临时文件中

            因为如果文件创建因任何原因失败,最终文件将永远处于损坏状态。如果你直接写入最终文件,而你的程序在中途崩溃了……它肯定会使最终文件处于无效状态。

            2 。是的

            “继承的”属性和权限当然会有所不同。但是大多数系统上的临时目录通常是预先配置的,供所有应用程序使用。但是,可能需要配置“最终文件”目录。例如,说“Program Files”文件夹和 Vista UAC。

            3 .在替换之前将 ACL 从最终文件复制到临时文件?

            【讨论】:

            • 也许我不清楚。 Q1 是一个非此即彼的问题。哪个更可取,或者重要吗?在 Q3 上,您的回答忽略了两件事:引导问题,以及我究竟如何复制 ACL?
            【解决方案8】:

            默认情况下,当 File.createTempFile() 中的后缀参数设置为 null 时,Android 会将 .tmp 作为后缀。我建议你就用那个。

            File file = File.createTempFile(imageFileName, null, storageDir);
            

            在您的应用中完成 .tmp 文件后,您应该自己调用 file.delete()。您不应该依赖 file.deleteOnExit(),因为绝对不能保证它会被 Android 系统/VM 使用。

            【讨论】:

              【解决方案9】:

              为什么不让它用户可配置?一些用户不喜欢临时文件污染他们当前的目录。

              【讨论】:

              • 如果应用程序没有失败,大概不会有临时文件留在工作目录中。不使其可配置的原因是因为我的 Q2 的答案是肯定的。
              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2012-10-27
              • 2013-12-06
              • 2014-07-15
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多