0

バイナリライターを使用して、いくつかの uint とバイト配列で構成されるレコードをファイルに書き込むメソッドがあります。このメソッドは、プログラムの一部として 1 秒間に約 10 回実行されます。コードは以下のとおりです。

iLogFileMutex.WaitOne();
using (BinaryWriter iBinaryWriter = new BinaryWriter(File.Open(iMainLogFilename, FileMode.OpenOrCreate, FileAccess.Write)))
{
    iBinaryWriter.Seek(0, SeekOrigin.End);
    foreach (ViewerRecord vR in aViewerRecords)
    {
        iBinaryWriter.Write(vR.Id);
        iBinaryWriter.Write(vR.Timestamp);
        iBinaryWriter.Write(vR.PayloadLength);
        iBinaryWriter.Write(vR.Payload);        
    }
}    
iLogFileMutex.ReleaseMutex();

上記のコードは正常に動作しますが、シーク呼び出しのある行を削除すると、結果のバイナリ ファイルが破損します。たとえば、特定のレコードが完全に欠落しているか、レコードの一部が存在しないだけで、大部分のレコードは問題なく書き込まれています。したがって、バグの原因は、ファイルを繰り返し開いたり閉じたりすると、ファイル内の現在の位置が常に最後にあるとは限らず、上書きされてしまうことだと思います。

私の質問は、ファイルを開いたときに現在の位置が最後にあることを C# が保証しないのはなぜですか?

PS: スレッド化の問題がこのバグの原因である可能性を除外しました

4

2 に答える 2

4

ファイルに追加する場合は、Open 呼び出しで FileMode.Append を使用する必要があります。そうしないと、ファイルの位置がファイルの末尾ではなく先頭に設定されて開きます。

于 2010-07-22T14:47:42.247 に答える
1

問題は、FileMode.OpenOrCreate と ViewerRecord メンバーのタイプの組み合わせです。それらの 1 つ以上が固定サイズの型ではなく、おそらく文字列です。

ファイルが既に存在する場合、問題が発生します。ファイルの先頭からデータの書き込みを開始し、既存のデータを上書きします。しかし、あなたが書いたものは偶然に既存のレコードを上書きするだけで、文字列はまったく同じサイズでなければなりません. 十分なレコードを書き込まないと、古いレコードをすべて上書きすることはできません。ファイルを読み取るときに問題が発生します。最後に書き込まれたレコードを読み取った後で、古いレコードの一部を読み取ることになります。しばらくジャンクになります。

レコードを固定サイズにしても問題は解決しません。良いレコードを読むことはできますが、それは古いレコードになります。取得する古いレコードの特定のセットは、書き込んだ新しいデータの量によって異なります。これは、文字化けしたデータを読み取るのと同じくらい悪いはずです。

本当に古いレコードを保持する必要がある場合は、FileMode.Append ファイルに追加する必要があります。そうでない場合は、ファイル FileMode.Create を書き直す必要があります。

于 2010-07-22T16:01:45.483 に答える