writeFileAtomically function
Writes contents to path, through a temporary file and a rename.
The rename is the point. A crash, a power cut or a full disk halfway
through a direct write leaves a truncated document where the good one was —
so one lost session becomes every future one, because the next read finds
something that will not parse. Writing beside it and renaming means the
worst case is a leftover .new file next to a document that is still
whole.
flush: true because a rename that beats the bytes to the disk is the same
failure with an extra step.
Throws what the filesystem throws. A caller that would rather report than fail — FileStorage is one — catches it; a caller that must tell somebody their level did not save — the editor is one — lets it out.
Implementation
Future<void> writeFileAtomically(String path, String contents) async {
final temporary = File('$path.new');
await temporary.writeAsString(contents, flush: true);
await temporary.rename(path);
}