Search code examples
c#.netbinaryreaderbinarywriter

BinaryReader - reading returns 1 record instead of multiple records


I am using BinaryWriter to write data to a log file.

However when I use BinaryReader to retrieve the data (within a loop), I am able to read the first 3 writes (integer, integer, byte[]), but the next iteration in the loop to read another 3 just seems to grab the rest of the data (and I cannot process it).

Here's the code:

write code:

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

read code:

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;
        }
    }
}

Appreciate your help in resolving!

EDIT:

I enclosed the binary write code in a using statement and I allow it to execute only 1 time so I know exactly how many bytes are written. When I process the read code, the basestream.length is way larger (i.e. I write 80 bytes and the basestream.length shows 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;
            }

Here is the binary data:

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

I'm really confused now!


Solution

  • Your BinaryReader code is correct, even though you could refactor it to be a little bit less repetitive and more concise.

    Based on your limited description i assume you are doing the writing wrong, and not the reading. Make sure that header.StructID and data.Length are integer types.

    Since you are invoking the BinaryReader from a Timer, than you have to be aware that the Write operation will write from the beginning of the existing file, since you have not advanced the writing stream to the correct position. That could cause some unwanted behavior (overwriting existing data etc.) and that is probably causing your reading issues. You should open your file in Append mode to prevent that.

    Here is a correct example of writing and reading using BinaryReader and BinaryWriter based on your example. It uses AppendMode on the file to prevent the issues you are seeing (i am reopening the file in a for loop to simulate your timer reopening the file and writing stuff to it):

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