Definition of reliable file writing: When a file is written to, one of the following must always be true:
This holds if the power goes out to the machine, if the operating system or the application crashes at some point during writing. It is not acceptable for the application to have to check for half-written data on a restart and clean up any mess.
Many applications will have serious problems if the data they write to disk is truncated or otherwise corrupted. Applications should always check for successful completion of writes, so a failure to write is not a problem - only a partial write.
The usual technique for reliably writing a file is to write all changes to a temporary file and then perform an atomic rename over the target filename. Unfortunately, to do this from .NET requires PInvoke:
[Flags]
enum MoveFileFlags
{
MOVEFILE_REPLACE_EXISTING = 0x00000001,
MOVEFILE_COPY_ALLOWED = 0x00000002,
MOVEFILE_DELAY_UNTIL_REBOOT = 0x00000004,
MOVEFILE_WRITE_THROUGH = 0x00000008,
MOVEFILE_CREATE_HARDLINK = 0x00000010,
MOVEFILE_FAIL_IF_NOT_TRACKABLE = 0x00000020
}
[
DllImport
(
"kernel32.dll",
SetLastError=true,
CharSet=CharSet.Auto
)
]
static extern bool MoveFileEx
(
string ExistingFileName,
string NewFileName,
MoveFileFlags Flags
);
public static void RenameWithOverwrite
(
string sourcePath,
string destinationPath
)
{
bool ok = MoveFileEx
(
sourcePath,
destinationPath,
MoveFileFlags.MOVEFILE_REPLACE_EXISTING
| MoveFileFlags.MOVEFILE_WRITE_THROUGH
);
if (!ok)
throw new Win32Exception
(Marshal.GetLastWin32Error());
}
If your application is running on Vista, it can take advantage of the transaction support built into NTFS. This requires a little more code but obviously there’s a lot more you can do with it.
If your code doesn’t use one of these techniques every time it writes an important file (something other than a diagnostic log), why not? Do you have a better way to ensure reliable writing? If so, I’d like to hear about it.