【问题标题】:Safely saving a file in Windows 10 IOT在 Windows 10 IOT 中安全保存文件
【发布时间】:2017-06-26 00:28:41
【问题描述】:

我的团队需要一种安全的方式来在 Windows 10 IOT 上保存文件(小于 100kb)。

文件不会损坏,但如果由于断电等原因保存失败,可以丢失最新版本。

由于文件 IO 发生了显着变化(不再有 File.Replace),我们不确定如何实现它。

我们可以看到:

var file = await folder.CreateFileAsync(fileName, CreationCollisionOption.OpenIfExists);
await Windows.Storage.FileIO.WriteTextAsync(file, data);

确实不可靠(它在停止调试或重置设备时反复中断。)我们最终得到一个损坏的文件(全零)和一个 .tmp 文件旁边。我们可以恢复这个 .tmp 文件 我不相信我们应该将我们的解决方案基于未记录的行为。

我们想尝试的一种方法是:

var tmpfile = await folder.CreateFileAsync(fileName+".tmp",
                               CreationCollisionOption.ReplaceExisting);
await Windows.Storage.FileIO.WriteTextAsync(tmpfile, data);

var file = await folder.CreateFileAsync(fileName, CreationCollisionOption.OpenIfExists);

// can this end up with a corrupt or missing file?
await tmpfile.MoveAndReplaceAsync(file); 

总之,有没有一种安全的方法可以将一些文本保存到一个永远不会损坏文件的文件中?

【问题讨论】:

  • 如果我的回答可以接受,请告诉我们,如果对您有帮助,请将我的回答标记为答案。
  • 我们有一个类似的问题附加到一个日志文件。创建新文件似乎是可靠的,正如您所说的“可靠不可靠”,覆盖现有文件。您的新更改将保存在预期的文件名中,但在写入失败时会创建一个具有先前内容的 TMP 文件。

标签: c# io windows-10-iot-core windowsiot


【解决方案1】:

不确定是否有最佳实践,但如果需要自己想出一些东西:

我会做一些事情,比如计算校验和并将其与文件一起保存。

下次保存时,不要覆盖,而是保存在上一个的旁边(应该是“已知良好”),并在验证新的保存成功完成后才删除上一个(连同校验和)

我还假设重命名操作不应该损坏文件,但我还没有研究过

【讨论】:

    【解决方案2】:

    这篇文章有一个很好的解释:Best practices for writing to files 关于在 UWP 中写入文件所涉及的底层过程。

    突出显示以下常见问题:

    • 文件部分写入。
    • 应用在调用其中一种方法时收到异常。
    • 这些操作会留下 .TMP 文件,其文件名与目标文件名相似。

    在讨论与convenience-vs-control 的权衡时不容易推断出的是,虽然创建或编辑操作更容易失败,因为它们做了很多事情,但重命名操作更容错,如果它们是不在文件系统周围物理写入位。

    您建议先创建一个临时文件,这是正确的,可能会为您提供良好的服务,但使用MoveAndReplaceAsync 意味着如果目标文件已经存在,您仍然容易受到这些已知问题的影响。

    UWP 将使用文件系统的事务模式,并可能创建源文件和目标文件的各种备份副本。

    您可以通过在调用MoveAndReplaceAsync 之前删除原始文件来控制最终元素,或者如果您的临时文件在同一个文件夹中,您可以简单地使用RenameAsync,这些组件较少,应该减少区域失败。

    @hansmbakker 有一个这样的答案,您如何确定文件写入是否成功取决于您,但是如果您需要的话,通过隔离繁重的写入操作并在覆盖您的原始文件之前对其进行验证是一个好主意防弹


    关于失败

    我观察了很多.TMP文件,当使用FileIO写的Append变体时,.TMP文件有追加之前的原始文件的内容,但实际文件并不总是包含所有原始客户端,有时它是新旧内容的混合,有时是

    根据我的经验,当您对写入操作的整个调用结构是异步的并且正确等待管道时,UWP 文件写入非常可靠。 并且您采取措施确保在任何时间点只有一个进程试图访问同一个文件。

    当您尝试从同步上下文中操作文件时,我们可以开始看到您已经确定的“不可靠”性质,这种情况经常发生在从旧同步操作转换到新同步操作的代码中异步 FileIO 操作的变体。

    确保调用您的 write 方法的代码是非阻塞的并且正确等待,这将允许您捕获任何可能引发的异常

    对于我们传统上具有同步意识的开发人员来说,尝试使用lock(){} 模式来确保对文件的单一访问是很常见的,但是您不能轻易地将await 放在lock 中,并且尝试这样做往往会成为源UWP 文件写入问题。

    如果您的代码有一个锁定机制来确保对文件的单例访问,请阅读这些文章以了解不同的方法,它们是旧的,但是一个很好的资源,涵盖了传统同步 C# 开发人员向异步和并行开发。

    我们遇到同步约束的其他时候是事件、计时器或处置上下文是首先写入文件的触发器。那里涉及不同的技术,如果您认为它可能会导致您的问题,请发布另一个涵盖该场景的问题。 :)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多