File.WriteAllText löscht keine Daten auf die Festplatte

Ich habe jetzt 3 Berichte erhalten, in denen festgestellt wurde, dass Benutzercomputer während der Verwendung meiner Software abstürzen. Die Abstürze beziehen sich nicht auf mein Programm, aber wenn sie die Konfigurationsdateien neu starten, sind alle von meinem Programm geschriebenen Dateien beschädigt.

Es gibt nichts Besonderes, wie die Dateien geschrieben werden, einfach eine Json-Repräsentation erstellen und mit File.WriteAllText () auf die Festplatte kopieren.

// save our contents to the disk
string json = JsonConvert.SerializeObject(objectInfo, Formatting.Indented);

// write the contents
File.WriteAllText(path, json);

Ich habe von einem Benutzer eine der Dateien erhalten und die Länge sieht ungefähr richtig aus (~ 3kb), aber die Inhalte sind alle 0x00.

Gemäß dem nachstehenden Beitrag sollte File.WriteAllText das Datei-Handle schließen und alle nicht geschriebenen Inhalte auf die Festplatte schreiben:

Wartet der Computer in meinem C # -Code, bis die Ausgabe abgeschlossen ist, bevor er fortfährt?

ABER, wie Alberto in den Kommentaren ausgeführt hat:

Wenn "System.IO.File.WriteAllText" abgeschlossen ist, wird der gesamte Text in den Dateisystem-Cache geschrieben und anschließend träge auf das Laufwerk geschrieben.

Daher gehe ich davon aus, dass hier die Datei gelöscht und mit 0x00 initialisiert wird, die Daten jedoch noch nicht geschrieben sind, wenn das System abstürzt.

Ich dachte daran, vielleicht eine Art temporäre Datei zu verwenden, damit der Prozess so aussieht:

Schreiben Sie neue Inhalte in die temporäre DateiOriginaldatei löschenTemporäre Datei in Original umbenennen

Ich glaube nicht, dass dies das Problem lösen wird, da ich davon ausgehe, dass Windows die Datei nur verschiebt, obwohl die E / A noch aussteht.

Gibt es eine Möglichkeit, die Maschine dazu zu zwingen, diese Daten auf die Festplatte zu kopieren, anstatt zu entscheiden, wann dies getan werden soll, oder eine bessere Möglichkeit, eine Datei zu aktualisieren?

AKTUALISIEREN:

Basierend auf den Vorschlägen von @usr, @mikez und @llya luzyanin habe ich eine neue WriteAllText-Funktion erstellt, die das Schreiben mit der folgenden Logik ausführt:

Erstellen Sie eine temporäre Datei mit dem neuen Inhalt, indem Sie das FileOptions.WriteThrough-Flag verwendenSchreibt die Daten auf die Festplatte (wird nicht zurückgegeben, bis der Schreibvorgang abgeschlossen ist)File.Replace, um den Inhalt der neuen temporären Datei in die reale Datei zu kopieren und eine Sicherungskopie zu erstellen

Wenn mit dieser Logik die endgültige Datei nicht geladen werden kann, überprüft mein Code, ob eine Sicherungsdatei vorhanden ist, und lädt diese stattdessen

Hier ist der Code:

public static void WriteAllTextWithBackup(string path, string contents)
{
    // generate a temp filename
    var tempPath = Path.GetTempFileName();

    // create the backup name
    var backup = path + ".backup";

    // delete any existing backups
    if (File.Exists(backup))
        File.Delete(backup);

    // get the bytes
    var data = Encoding.UTF8.GetBytes(contents);

    // write the data to a temp file
    using (var tempFile = File.Create(tempPath, 4096, FileOptions.WriteThrough))
        tempFile.Write(data, 0, data.Length);

    // replace the contents
    File.Replace(tempPath, path, backup);
}

Antworten auf die Frage(1)

Ihre Antwort auf die Frage