我需要在项目中写入一个大文件。
我学到的东西:
我不应该将大文件直接写入目标路径, 因为这样可能会留下不完整的文件,以防应用在编写时崩溃。
相反,我应该写一个临时文件并移动(重命名)它。 (称为原子文件操作)
我的代码段:
[NotNull]
public static async Task WriteAllTextAsync([NotNull] string path, [NotNull] string content)
{
string temporaryFilePath = null;
try {
temporaryFilePath = Path.GetTempFileName();
using (var stream = new StreamWriter(temporaryFilePath, true)) {
await stream.WriteAsync(content).ConfigureAwait(false);
}
File.Delete(path);
File.Move(temporaryFilePath, path);
}
finally {
if (temporaryFilePath != null) File.Delete(temporaryFilePath);
}
}
我的问题:
如果应用在File.Delete
和File.Move
之间崩溃,文件将丢失。我可以避免吗?
写大文件还有其他最佳实践吗?
我的代码上有什么建议吗?
答案 0 :(得分:7)
如果应用程序在File.Delete和File.Move之间崩溃,则文件将丢失。我可以避免吗?
我不知道,但是您可以检测到它-如果使用更可预测的文件名,则可以从中恢复。如果您稍微调整一下过程以使用三个文件名,则将有所帮助:目标文件,“新”文件和“旧”文件。该过程变为:
foo.txt.new
)foo.txt.old
)您将拥有三个文件,每个文件可能存在或不存在。当您开始读取新文件时,这可以帮助您检测情况:
注意:之前我没有意识到File.Replace
,但是我怀疑它有效只是一种更简单,可能更有效的方式来处理已经在执行的代码。 (太好了-使用它!)恢复过程仍然相同。
答案 1 :(得分:5)
您可以使用File.Replace
代替删除和移动文件。万一发生硬故障(断电或类似情况),您将永远丢失数据,您必须依靠它。