2009-09-15 3 views
6

Ok, so zu erklären; Ich entwickle für ein System, das zu irgendeinem Zeitpunkt einen Stromausfall erleiden kann, ein Punkt, den ich gerade teste, ist direkt nachdem ich eine Datei mit einem StreamWriter geschrieben habe. Der folgende Code:Stromausfall nach StreamWriter.Close() erzeugt leere Datei, warum?

// Write the updated file back out to the Shell directory. 
using (StreamWriter shellConfigWriter = 
     new StreamWriter(@"D:\xxx\Shell\Config\Game.cfg.bak")) 
{ 
    for (int i = 0; i < configContents.Count; i++) 
    { 
     shellConfigWriter.WriteLine(configContents[i]); 
    } 
    shellConfigWriter.Close(); 
} 

FileInfo gameCfgBackup = new FileInfo(@"D:\xxx\Shell\Config\Game.cfg.bak"); 
gameCfgBackup.CopyTo(@"D:\xxx\Shell\Config\Game.cfg", true); 

Schreibt den Inhalt von shellConfigWriter (a List von Strings) in eine Datei als Zwischenspeicher verwendet wird, dann wird es über das Original kopiert. Jetzt, nachdem dieser Code ausgeführt wurde, geht der Strom verloren, beim erneuten Start der Datei existiert die Datei Game.cfg und hat die richtige Größe, ist aber komplett leer. Zuerst dachte ich, dass dies daran liegt, dass Write-Caching auf der Festplatte aktiviert ist, aber selbst wenn es ausgeschaltet ist, tritt es immer noch auf (wenn auch nicht so oft).

Alle Ideen wären sehr willkommen!

Update: Ok, so dass nach den .Close() Aussagen zu entfernen und riefen .Flush() nach jedem Schreibvorgang beenden die Dateien noch leer nach oben. Ich könnte noch einen Schritt weiter gehen und zuerst eine Sicherungskopie der Originaldatei erstellen, bevor ich die neue erstellen würde, und dann habe ich genügend Sicherungskopien, um eine Integritätsprüfung durchzuführen, aber ich denke nicht, dass sie helfen wird, das zugrunde liegende Problem zu lösen (wenn ich es schreibe, speichere und schließe eine Datei ... tut es nicht!).

+0

Ist 'Game.cfg.bak' leer als auch? –

+0

Ja, sie sind beide leer. :( – Siyfion

+2

C# hat einen Puffer, das Betriebssystem hat einen Puffer oder zwei und Ihre physische Festplatte hat einen Puffer. Ich denke, Sie können nur die ersten beiden von C# beeinflussen. Sie verlieren immer einige Daten in einer Stromausfall Situation, die Frage ist, wie viel. – Pod

Antwort

11

Halten Sie das OS setzen:

using (Stream fs = new FileStream(@"D:\xxx\Shell\Config\Game.cfg.bak", FileMode.Create, FileAccess.Write, FileShare.None, 0x1000, FileOptions.WriteThrough)) 
    using (StreamWriter shellConfigWriter = new StreamWriter(fs)) 
    { 
     for (int i = 0; i < configContents.Count; i++) 
     { 
      shellConfigWriter.WriteLine(configContents[i]); 
     } 
     shellConfigWriter.Flush(); 
     shellConfigWriter.BaseStream.Flush(); 
    } 
+0

Fantastisch! Great find;) – Siyfion

+1

Eine Alternative zu "new FileStream" ist die statische File.Create Methode: "File.Create (@" D: \ xxx \ Shell \ Konfig \ Game.cfg.bak ", 0x1000, FileOptions.WriteThrough, null) ". Es hat ein paar weniger Parameter und könnte im Code sauberer aussehen. –

6

Zuerst müssen Sie shellConfigWriter.Close() dort nicht anrufen. Die using Anweisung wird sich darum kümmern. Was Sie stattdessen tun könnten, um gegen Stromausfall zu schützen, ist Anruf shellConfigWriter.Flush().


aktualisieren
Etwas anderes möchten Sie vielleicht zu prüfen, ist, dass, wenn ein Stromausfall wirklich jede Zeit passieren kann, ist es in der Mitte eines Schreib passieren könnte, so dass nur der Teil Bytes machen es zu einer Datei. Es gibt wirklich keine Möglichkeit, das zu stoppen.

Um vor diesen Szenarien zu schützen, ist es eine übliche Prozedur, Zustands/Zustands-Flag-Dateien zu verwenden. Sie verwenden die Existenz oder Nichtexistenz einer Null-Byte-Datei mit einem bestimmten Namen im Dateisystem, um Ihrem Programm zu sagen, wo es bei der Fortsetzung des Programms wieder aufgenommen werden soll. Dann erstellen oder zerstören Sie nicht die Dateien, die einen bestimmten Zustand auslösen, bis Sie sicher sind Sie haben diesen Zustand erreicht und die vorherige abgeschlossen.

Die Kehrseite hier ist, dass es bedeuten könnte, dass hin und wieder viel Arbeit wegwerfen. Der Vorteil ist jedoch, dass der funktionale Teil Ihres Codes wie normal aussieht: Es gibt nur wenig zusätzliche Arbeit, um das System ausreichend robust zu machen.

+0

Einverstanden, ich hatte nicht die .Close() Methode dort ursprünglich aus genau diesem Grund, aber ich lief die Dinge zu versuchen! Ich werde versuchen, nach jedem Schreibanruf zu spülen, sehen was passiert dann. – Siyfion

+0

Kein Glück, schrieb immer noch keine Zeile. – Siyfion

0

Sie wollen von Puffern der Ausgabe mit dem FileOptions Parameter des Konstrukteurs-FileStream Objekt AutoFlush = true;

+0

Yeh könnte ich, aber für den Zweck dieses Beispiels Code ist es 1 Zeile so; Lege alle für Iteration ab oder setze AutoFlush auf True. Es erzeugt immer noch das gleiche Ergebnis, nämlich dass es immer noch eine leere Datei erzeugt. – Siyfion

+0

Sind Sie sicher, dass Sie nicht nur leere Zeilen in die Datei schreiben? ; p – leppie