【问题标题】:BinaryReader - reading returns 1 record instead of multiple recordsBinaryReader - 读取返回 1 条记录而不是多条记录
【发布时间】:2014-10-24 16:03:34
【问题描述】:

我正在使用 BinaryWriter 将数据写入日志文件。

但是,当我使用 BinaryReader 检索数据(在循环内)时,我能够读取前 3 次写入(整数、整数、字节 []),但循环中的下一次迭代读取另外 3 次似乎获取其余数据(我无法处理)。

代码如下:

编写代码:

writer.Write(header.StructID);
writer.Write(data.Length);
writer.Write(data);

阅读代码:

using (FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
    using (BinaryReader br = new BinaryReader(fs))
    {
        long bytesRead = 0;
        long readerLen = br.BaseStream.Length;

        //read 1st record
        int id = br.ReadInt32();
        int len = br.ReadInt32();
        byte[] data = br.ReadBytes(len);
        bytesRead += (sizeof(int) * 2) + data.Length;

        while (bytesRead < readerLen)
        {
            //TODO:process data

            //read next
            id = br.ReadInt32();
            len = br.ReadInt32();
            data = br.ReadBytes(len);
            bytesRead += (sizeof(int) * 2) + data.Length;
        }
    }
}

感谢您帮助解决问题!

编辑:

我将二进制写入代码包含在 using 语句中,并允许它仅执行 1 次,因此我确切知道写入了多少字节。当我处理读取的代码时,basestream.length 更大(即我写了 80 个字节,basestream.length 显示为 1144)。

    using (writer = new BinaryWriter(File.Open(filename, FileMode.OpenOrCreate)))
            {
                long pos = writer.BaseStream.Position;
                writer.Write(header.StructID);
                writer.Write(data.Length);
                writer.Write(data);
                m_LoggingEnabled = false;
            }

这是二进制数据:

CE 00 00 00 48 00 00 00 AD A2 3B 94 76 08 A7 3E 7A 9A 80 9D CC 1A 2B 3F 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 F0 BF 91 01 00 00 00 00 00 00 00 00 00 00 00 00 F0 3F 01 00 00 00 00 00 00 00 CE 00 00 00 48 00 00 00 AD A2 3B 94 76 08 A7 3E 7A 9A 80 9D CC 1A 2B 3F 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 F0 BF 92 01 00 00 00 00 00 00 00 00 00 00 00 2A 7A BE 01 00 00 00 50 64 63 3D CE 00 00 00 48 00 00 00 D8 41 B1 19 01 A3 86 BE E2 E2 7A 22 6F 1F 2B 3F 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 F0 BF 91 01 00 00 00 00 00 00 00 00 00 00 00 00 F0 3F 01 00 00 00 00 00 00 00

我现在真的很困惑!

【问题讨论】:

  • 嗯,当您致电br.ReadBytes(len) 时,您已将所有内容读入data。您期望其他数据来自哪里?您的问题目前还不清楚。
  • 此外,看起来您最好使用do.. while 循环。
  • 嗯,@Jon,怎么会这样?如果数据被正确写入,他将如何读取超过 len 个字节,这有望构成一条记录的其余部分..? (我可能很快就不得不把脚放在不属于它的地方,但是,我不明白..)他似乎只是在循环中覆盖了数据..
  • @Radiohead 你确定吗?还没有处理代码 - 您是否已通过调试器逐步完成...?
  • 使用 AppendMode 来防止您看到的问题。看看我更新的解释;)

标签: c# .net binaryreader binarywriter


【解决方案1】:

您的BinaryReader 代码是正确的,尽管您可以将其重构为更少重复且更简洁。

根据您有限的描述,我认为您的写作错误,而不是阅读错误。确保header.StructIDdata.Length 是整数类型。

由于您从 Timer 调用 BinaryReader,因此您必须注意 Write 操作将从现有文件的开头写入,因为您尚未将写入流推进到正确的位置。这可能会导致一些不需要的行为(覆盖现有数据等)并且这可能会导致您的阅读问题。您应该以Append 模式打开文件以防止这种情况发生。

这是基于您的示例使用 BinaryReader 和 BinaryWriter 进行写入和读取的正确示例。它在文件上使用 AppendMode 来防止您看到的问题(我在 for 循环中重新打开文件以模拟您的计时器重新打开文件并向其写入内容):

var stuffToWrite = new List<byte[]>()
{
    new byte[72],
        new byte[72],
        new byte[72],
};

for (int i = 0; i < stuffToWrite.Count; i++)
{

    using (var file = File.Open(filename, FileMode.Append))
    using (var binaryWriter = new BinaryWriter(file))
    {
        binaryWriter.Write(206);
        binaryWriter.Write((stuffToWrite[i].Length));
        binaryWriter.Write(stuffToWrite[i]);
    }
}

using (var fs = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
using (var br = new BinaryReader(fs))
{
    do
    {
        int id = br.ReadInt32();
        int len = br.ReadInt32();
        byte[] data = br.ReadBytes(len);

        // Process Data

    } while (br.BaseStream.Position < br.BaseStream.Length);
}

【讨论】:

  • 嗨,Zen,我确定我做错了什么,但是在应用您的上述建议后,我遇到了这样的情况:
  • 我在写入数据时观察 basestream.position 的前进。它按预期前进。当我阅读时,我可以成功读取第一组数据(id,len,data)。在通过 do/while 循环的第二次迭代时,此行返回垃圾: int id = br.ReadInt32();从那时起,一切都失败了。
  • 读取时,basestream.position 正在按预期移动。但是当循环的第二次迭代应该返回一个整数时,我得到了可怕的 id = -858993459。
  • 在 do/while 循环的第二次迭代中,在 id= br.readint32(); 行,basestream.position 处于执行 readint32 的预期位置。
  • 我认为问题在于您的日志文件数据已损坏。您是否尝试过删除日志文件并使用新的日志文件重新运行?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多