c# - File.WriteAllText not flushing data to disk -


i've had 3 reports of user's machines crashing while using software.. crashes not related program when restart config files program writes corrupt.

there nothing special how files being written, creating json representation , dumping disk using file.writealltext()

// save our contents disk string json = jsonconvert.serializeobject(objectinfo, formatting.indented);  // write contents file.writealltext(path, json); 

i've had user send me 1 of files , length looks right (~3kb) contents 0x00.

according post below file.writealltext should close file handle, flushing unwritten contents disk:

in c# code computer wait until output complete before moving on?

but, pointed out alberto in comments:

system.io.file.writealltext when completes, flush text filesystem cache, then, lazily written drive.

so presume happening here file being cleared , initialized 0x00 data not yet written when system crashes.

i thinking of maybe using sort of temp file process this:

  1. write new contents temp file
  2. delete original file
  3. rename temp file original

i don't think solve problem presume windows move file though io still pending.

is there way can force machine dump data disk instead of deciding when or perhaps better way update file?

update:

based on suggestions @usr, @mikez , @llya luzyanin i've created new writealltext function performs write using following logic:

  1. create temp file new contents using fileoptions.writethrough flag
  2. writes data disk (won't return until write has completed)
  3. file.replace copy contents of new temp file real file, making backup

with logic, if final file fails load, code check backup file , load instead

here code:

public static void writealltextwithbackup(string path, string contents) {     // generate temp filename     var temppath = path.gettempfilename();      // create backup name     var backup = path + ".backup";      // delete existing backups     if (file.exists(backup))         file.delete(backup);      // bytes     var data = encoding.utf8.getbytes(contents);      // write data temp file     using (var tempfile = file.create(temppath, 4096, fileoptions.writethrough))         tempfile.write(data, 0, data.length);      // replace contents     file.replace(temppath, path, backup); } 

you can use filestream.flush force data disk. write temp file , use file.replace atomically replace target file.

i believe guaranteed work. file systems give weak guarantees. these guarantees hardly ever documented , complex.

alternatively, can use transactional ntfs if available. available .net.

fileoptions.writethrough can replace flush still need temp file if data can exceed single cluster in size.


Comments

Popular posts from this blog

javascript - Jquery show_hide, what to add in order to make the page scroll to the bottom of the hidden field once button is clicked -

javascript - Highcharts multi-color line -

javascript - Enter key does not work in search box -