0

我有一种方法,它使用二进制写入器将由少数 uint 和字节数组组成的记录写入文件。作为我程序的一部分,此方法每秒执行大约十几次。代码如下:

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();

上面的代码工作正常,但如果我用 seek 调用删除该行,生成的二进制文件就会损坏。例如,某些记录完全丢失或部分记录不存在,尽管绝大多数记录都写得很好。所以我想这个错误的原因是当我反复打开和关闭文件时,文件中的当前位置并不总是在最后,事情会被覆盖。

所以我的问题是:当我打开文件时,为什么 C# 不能确保当前位置位于末尾?

PS:我已排除线程问题导致此错误

4

2 回答 2

4

如果要附加到文件,则必须在 Open 调用中使用 FileMode.Append,否则文件将打开,其位置设置为文件的开头,而不是结尾。

于 2010-07-22T14:47:42.247 回答
1

问题是 FileMode.OpenOrCreate 和 ViewerRecord 成员的类型的组合。其中一个或多个不是固定大小的类型,可能是字符串。

当文件已经存在时,事情就会出错。您将在文件开头开始写入数据,覆盖现有数据。但是你写的只是偶然覆盖了现有的记录,字符串必须是完全相同的大小。如果您没有写入足够的记录,那么您将不会覆盖所有旧记录。并且在读取文件时遇到麻烦,您将在读取最后一条写入记录后读取旧记录的一部分。你会得到一段时间的垃圾。

将记录设置为固定大小并不能真正解决问题,您会读到好记录,但它会是旧记录。您将获得哪些特定的旧记录集取决于您写入了多少新数据。这应该和读取乱码数据一样糟糕。

如果您确实需要保留旧记录,则应附加到文件 FileMode.Append。如果不这样做,则应重写文件 FileMode.Create。

于 2010-07-22T16:01:45.483 回答