Reputation: 363
I need to write a big file in my project.
What I learned:
I should NOT write the big file directly to the destination path, because this may leave a incomplete file in case the app crash while writing it.
Instead, I should write to a temporary file and move (rename) it. (called atomic file operation)
My code snippet:
[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);
}
}
My Question:
The file will be missing if the app crashes between File.Delete
and File.Move
. Can I avoid this?
Is there any other best practice for writing big files?
Is there any suggestion on my code?
Upvotes: 3
Views: 1165
Reputation: 1499790
The file will be missing if the app crashes between File.Delete and File.Move. Can I avoid this?
Not that I'm aware of, but you can detect it - and if you use a more predictable filename, you can recover from that. It helps if you tweak the process somewhat to use three file names: the target, a "new" file and an "old" file. The process becomes:
foo.txt.new
)foo.txt.old
)You then have three files, each of which may be present or absent. That can help you to detect the situation when you come to read the new file:
Note: I was unaware of File.Replace
before, but I suspect it's effectively just a simpler and possibly more efficient way of doing the code you're already doing. (That's great - use it!) The recovery process would still be the same though.
Upvotes: 7
Reputation: 624
You can use File.Replace
instead of deleting and moving files. In case of hard fault (electricity cut or something like this) you will always lost data, you have to count with that.
Upvotes: 6