1

I have following code to save data:

File.Copy("data.txt", "data_backup.txt", true);
File.WriteAllText("data.txt", JsonConvert.SerializeObject(new
{
    bool1,
    string1,
    decimal1,
    decimal2,
    int1,
    datetime,
    object1,
    object2
}, new JsonSerializerSettings { Formatting = Formatting.Indented, Converters = new List<JsonConverter>() { new DontIntendArray() } }));

which my program executes every 15 seconds. Size of data.txt is about 9 MB.

From time to time when my computer crashes then after restart I find out that data.txt is full of NULL characters while its size remains about 9 MB. That is why I added data_backup.txt line but it doesn't help as it saves files full of NULLs as well.

Note that this doesn't happen during every computer but apparently only when it crashes while this code is being executed.

I experienced this behavior while using XMP profile on my RAM which was unstable and caused crash from time to time. It was exactly the same on two different computers with unstable XMR profile. I also experienced it during electricity outage.

I understand that I can't expect crashing computer to flawlessly execute all code and only then crash. However, is there any trick I can use to prevent loss of content of files that are just being written to or saved while or moment before computrer crashes? The whole purpose of regularly saving these variables into file is to prevent loss of data in case of computer crash but apparently this approach doesn't always work.

LukAss741
  • 771
  • 1
  • 7
  • 24
  • Can you detect false/corrupted data by code ie automatically? – TaW May 24 '18 at 21:17
  • 1
    I haven't tested it by crashing it on purpose yet. I get your point of using File.Copy after WriteAllText only if it is not currupted. Thank you. – LukAss741 May 24 '18 at 21:36

1 Answers1

1

You should save to a new filename, then move the new file to replace the original one after it saves. This way, no matter when you get interrupted, you always have one intact copy.

SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
  • I don't think this approach would be any different because since both data.txt and data_backup.txt are empty it means the whole code is executed but any file write operation writes incorrect data so that these files are empty. It is probably due to loss of data in RAM while CPU finishes a few of its tasks. Hence saving it to new filename would be executed but file content will be only nulls. This corrupted will will then probably only replace the original. Or am I not getting something? – LukAss741 May 24 '18 at 21:07
  • @LukAss741: No; the point of this is to preserve the old file when it isn't empty – SLaks May 24 '18 at 21:24
  • So do you mean ´File.WriteAllText("data_new.txt"´ and then ´File.Copy("data_new.txt", "data.txt", true);´? – LukAss741 May 24 '18 at 21:32
  • Yes, except move rather than copy. – SLaks May 24 '18 at 21:35
  • 1
    I am skeptical this approach would be any different because File.WriteAllText is executed but writes nulls and File.Move then overwrites last backup with corrupted data_new.txt which is full of nulls. I might test it tomorrow anyway. It is hard to reproduce anyway. – LukAss741 May 24 '18 at 21:42
  • 1
    @LukAss741: `Move` should be an atomic operation (it updates the file table; it doesn't move bytes) – SLaks May 25 '18 at 00:30
  • In the mean time I found https://stackoverflow.com/questions/25366534/file-writealltext-not-flushing-data-to-disk?rq=1 so I flagged this as duplicate. Thanks for your advise anyway. – LukAss741 May 25 '18 at 14:29