【问题标题】:binarywriter not opening file at end of streambinarywriter 未在流结束时打开文件
【发布时间】:2010-07-22 14:43:29
【问题描述】:

我有一种方法,它使用二进制写入器将由少数 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:我已排除线程问题导致此错误

【问题讨论】:

    标签: c# file corruption binarywriter


    【解决方案1】:

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

    【讨论】:

    • 非常正确,我应该在我的帖子中指出这一点。但是,为什么我仍然会收到大量记录,包括第一个记录,写得没有任何问题,然后在文件中途的某个地方我写了一半的记录,然后那些之后的记录也很好。附加或缺少它们不会导致这种情况吗?当然,我应该只获取文件中实际存在的最后一个记录列表吗?
    • 那么您发布的代码实际上不是有问题的代码吗?
    【解决方案2】:

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

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

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

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

    【讨论】:

      猜你喜欢
      • 2023-03-28
      • 2015-12-17
      • 1970-01-01
      • 1970-01-01
      • 2012-10-19
      • 1970-01-01
      • 1970-01-01
      • 2016-06-18
      • 1970-01-01
      相关资源
      最近更新 更多