我的团队需要一种防弹的方法来在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); 总而言之,有没有一种安全的方法可以将一些文本保存到文件中,而不会损坏文件?
发布于 2017-06-27 04:19:40
我不确定这方面是否有最佳实践,但如果需要我自己提出一些建议:
我会做一些事情,比如计算校验和,并将其与文件一起保存。
下一次保存时,不要覆盖,而是紧挨着前一次保存(应该是"known“),并在确认新的保存成功后才删除前一次(连同校验和)
另外,我假设重命名操作不会损坏文件,但我没有研究过这一点
发布于 2019-11-28 09:29:54
这篇文章有一个很好的解释:Best practices for writing to files关于在UWP中写入文件所涉及的底层进程。
突出显示了以下常见问题:
在讨论与convenience-vs-control的权衡时,不容易推断的是,虽然创建或编辑操作更容易失败,因为它们做了很多事情,但如果重命名操作不是在文件系统周围物理地写位,则它们具有更高的容错能力。
您建议首先创建一个临时文件,这是正确的,可能会很好地为您服务,但使用MoveAndReplaceAsync意味着如果目标文件已经存在,您仍然容易受到这些已知问题的影响。
UWP将对文件系统使用事务模式,并且可以创建源文件和目标文件的各种备份副本。
您可以通过在调用MoveAndReplaceAsync之前删除原始文件来控制最后一个元素,或者如果您的临时文件在同一文件夹中,则可以简单地使用RenameAsync,这些组件较少,这应该会减少失败的区域。
@hansmbakker有一个大致的答案,如何识别文件写入是否成功取决于你,但是如果你需要防弹的话,通过隔离繁重的写操作并在覆盖你的原始文件之前验证它是一个好主意。
关于失败
我观察了很多.TMP文件,当使用FileIO编写的附加变体时,.TMP文件在附加之前具有原始文件的内容,但实际文件并不总是具有原始客户端的所有内容,有时是新旧内容的混合,有时是
在我的经验中,当你对写操作的整个调用结构是异步的,并且正确地等待管道时,
文件写是非常可靠的。并采取措施确保在任何时间点只有一个进程尝试访问同一文件。
当您尝试从同步上下文操作文件时,我们可以开始看到您所识别的“不可靠”性质,这在从旧的同步操作过渡到新的FileIO操作的异步变体的代码中发生了很多。
确保调用write方法的代码是非阻塞的,并且正确等待,这将允许您捕获任何可能引发的异常
对于我们传统上具有同步意识的开发人员来说,尝试使用lock(){}模式来确保对文件的单一访问是很常见的,但您不能轻松地在lock中使用await,这样做的尝试往往会成为UWP文件写入问题的根源。
如果您的代码具有锁定机制以确保对文件的单独访问,请阅读这些文章以了解不同的方法,这些文章虽然陈旧,但却是一个很好的资源,涵盖了传统的同步C#开发人员向异步和并行开发的过渡。
我们遇到同步约束的其他时候是,当事件、计时器或Dispose上下文是写入文件的触发器时。有不同的技术可以涉及到那里,如果你认为它可能会导致你的问题,请发布另一个涵盖该场景的问题。:)
https://stackoverflow.com/questions/44751794
复制相似问题