C# BinaryReader.Read() gets junk to start with
Asked Answered
A

1

6

I am trying to figure out what I am doing wrong here. I am attempting to use a Binary Reader to ease getting an initial four bytes from a stream into an Int32 value that tells me how long the rest of the data is to be expected.

static void Main(string[] args)
{
    MemoryStream stream = new MemoryStream();

    BinaryWriter writer = new BinaryWriter(stream);

    string s = "Imagine this is a very very long string.";

    writer.Write(s.Length);
    writer.Write(s);
    writer.Flush();

    BinaryReader reader = new BinaryReader(stream);
    reader.BaseStream.Seek(0, SeekOrigin.Begin);

    char[] aChars = new char[reader.ReadInt32()];
    reader.Read(aChars, 0, aChars.Length);
    Console.WriteLine(new string(aChars));
}

The output should be the input, but I get this (Note that the first character changes from string to string)

(Imagine this is a very very long string

Can someone explain to me what I am doing wrong? Ideally the second read would continue until the total read bytes was equal to the value of the first four bytes.. this code is just a simplification to show the problem I am running into. The position of the stream seems correct (4) but it almost seems like it starts reading at 2.

Ansley answered 24/11, 2010 at 0:3 Comment(3)
Hehe, thanks... and I was. Unfortunately for me the BinaryReader doesnt mention that the Writer stores extra data for a string than the string ;)Ansley
BinaryWriter.Write(string): "A length-prefixed string represents the string length by prefixing to the string a single byte or word that contains the length of that string. This method first writes the length of the string as a UTF-7 encoded unsigned integer, and then writes that many characters to the stream by using the BinaryWriter instance's current encoding."Pifer
BinaryReader.ReadString: "Reads a string from the current stream. The string is prefixed with the length, encoded as an integer seven bits at a time."Pifer
U
8

BinaryWriter.Write(String) writes a length-prefixed string to this stream. This means it first writes the length of the string to the stream, and then the string using some encoding. The length is encoded seven bits at a time, not as 32-bit integer.

If you want to read from the stream, you should use BinaryReader.ReadString, which reads a length-prefixed string from the stream.

Unwitnessed answered 24/11, 2010 at 0:9 Comment(5)
Will it automatically wait for the rest of the data to show up then if it does not initially have it in the stream?Ansley
Not only does it write the length first, but the length is written in a 7-bit encoding. So strings that are less than 128 bytes long have a one-byte length prefix, etc.Torp
@James: Yes, it will wait for the data.Torp
@James: Yes, ReadString returns the entire string, not just a part of it. But it doesn't "wait" for anything. It just reads the length and the bytes that make up the string from the stream. If there are less bytes then indicates by the length prefix, it will throw an Exception.Unwitnessed
[facepalm] Thanks guys.. Ive been reading all the 'reader' documentation for hours now trying to figure out where the extra data is coming from and its the write process that has had me chasing ghosts! Will mark this as the answer when I can in a few min..Ansley

© 2022 - 2024 — McMap. All rights reserved.