StreamWriter.Close()が空のファイルを生成した後の電力損失、なぜですか?
-
07-07-2019 - |
質問
わかりました、説明するために;私は、いつでも電源障害が発生する可能性のあるシステム向けに開発しています。テストしているポイントの1つは、StreamWriterを使用してファイルを書き出した直後です。以下のコード:
// 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);
shellConfigWriter
(文字列の List
)の内容を一時ストアとして使用されるファイルに書き込み、元のファイルにコピーします。このコードの実行が終了すると、電源が失われ、再び起動すると、ファイル Game.cfg
が存在し、正しいサイズになりますが、完全に空白になります。最初は、これはハードドライブで書き込みキャッシュが有効になっているためだと思っていましたが、それをオフにしてもまだ発生します(頻度は低いですが)。
どんなアイデアでも大歓迎です!
更新: OK空白になります。さらに一歩進んで元のファイルのバックアップを作成してから新しいファイルを作成し、整合性チェックを行うのに十分なバックアップがありますが、根本的な問題を解決するのに役立つとは思いません(ファイルに書き込む、フラッシュする、閉じるように指示したときに...しません!)
解決
FileStream
オブジェクトのコンストラクターの FileOptions
パラメーターを使用して、OSが出力をバッファリングしないようにします。
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();
}
他のヒント
まず、そこで shellConfigWriter.Close()
を呼び出す必要はありません。 using
ステートメントがそれを処理します。停電を防ぐために代わりに行うことは、 shellConfigWriter.Flush()
を呼び出すことです。
更新
他に考慮したいのは、停電が本当にいつでも発生する可能性がある場合、書き込みの途中で発生する可能性があり、一部のバイトのみがファイルに書き込まれることです。それを止める方法は本当にありません。
これらのシナリオから保護するための一般的な手順は、状態/条件フラグファイルを使用することです。特定の名前を持つゼロバイトファイルのファイルシステム上の存在または非存在を使用して、再開時にプログラムをどこで再びピックアップするかをプログラムに指示します。その後、特定の状態に到達し、その状態に到達して前の状態を完了するまで、特定の状態をトリガーするファイルを作成または破棄しないでください。
ここでの欠点は、多くの仕事を時々捨てることを意味するかもしれないということです。しかし、利点は、コードの機能部分が通常のように見えることです。システムを十分に堅牢にするために行う余分な作業はほとんどありません。
AutoFlush = true;