reading memory stream in byte chunks
-
I want to create a memory stream as follows [1byte][4bytes][n bytes][4 bytes][n bytes][4 bytes][n bytes] ....ect my first stream consisted of [0][12][Hello World.] _packetWriter.WriteOpCode((byte)opCode); _packetWriter.WriteMessage("Hello World."); _client.Client.Send(_packetWriter.GetPacketBytes()); when I read it back I get the following, and when I look at the byte arrays I'm seeing some bytes from the previous chunk 10/09/2022 11:39:00 : Opcode Found With Value 0 10/09/2022 11:39:00 : Chunk Found With Value 12 10/09/2022 11:39:00 : Message Found With Value Hello Worl can anybody help thanks madaxe
public class PacketWriter : BinaryWriter
{
public MemoryStream MemoryStream;
public BinaryWriter BinaryWriter;public PacketWriter() { MemoryStream = new MemoryStream(); BinaryWriter = new BinaryWriter(MemoryStream); } public void WriteOpCode(byte opCode) { MemoryStream.WriteByte(opCode); } public void WriteNextChunckSize(int chunkSize) { BinaryWriter.Write((Int32)chunkSize); } public void WriteMessage(string message) { WriteNextChunckSize(message.Length); BinaryWriter.Write(message); } public byte\[\] GetPacketBytes() { return MemoryStream.ToArray(); } }
public class PacketReader : BinaryReader
{
private NetworkStream _memoryStream;
public PacketReader(NetworkStream memoryStream) : base(memoryStream)
{
_memoryStream = memoryStream;
}public int ReadOpCode() { return \_memoryStream.ReadByte(); } public string ReadMessage(int chunkSize) { byte\[\] readMessage; readMessage = new byte\[chunkSize\]; \_memoryStream.Read(readMessage, 0, chunkSize); var message = Encoding.ASCII.GetString(readMessage); return message; } public int ReadChunkSize() { byte\[\] readChunkSize; readChunkSize = new byte\[4\]; \_memoryStream.Read(readChunkSize, 0, 3); return BitConverter.ToInt32(readChunkSize, 0); } }
-
I want to create a memory stream as follows [1byte][4bytes][n bytes][4 bytes][n bytes][4 bytes][n bytes] ....ect my first stream consisted of [0][12][Hello World.] _packetWriter.WriteOpCode((byte)opCode); _packetWriter.WriteMessage("Hello World."); _client.Client.Send(_packetWriter.GetPacketBytes()); when I read it back I get the following, and when I look at the byte arrays I'm seeing some bytes from the previous chunk 10/09/2022 11:39:00 : Opcode Found With Value 0 10/09/2022 11:39:00 : Chunk Found With Value 12 10/09/2022 11:39:00 : Message Found With Value Hello Worl can anybody help thanks madaxe
public class PacketWriter : BinaryWriter
{
public MemoryStream MemoryStream;
public BinaryWriter BinaryWriter;public PacketWriter() { MemoryStream = new MemoryStream(); BinaryWriter = new BinaryWriter(MemoryStream); } public void WriteOpCode(byte opCode) { MemoryStream.WriteByte(opCode); } public void WriteNextChunckSize(int chunkSize) { BinaryWriter.Write((Int32)chunkSize); } public void WriteMessage(string message) { WriteNextChunckSize(message.Length); BinaryWriter.Write(message); } public byte\[\] GetPacketBytes() { return MemoryStream.ToArray(); } }
public class PacketReader : BinaryReader
{
private NetworkStream _memoryStream;
public PacketReader(NetworkStream memoryStream) : base(memoryStream)
{
_memoryStream = memoryStream;
}public int ReadOpCode() { return \_memoryStream.ReadByte(); } public string ReadMessage(int chunkSize) { byte\[\] readMessage; readMessage = new byte\[chunkSize\]; \_memoryStream.Read(readMessage, 0, chunkSize); var message = Encoding.ASCII.GetString(readMessage); return message; } public int ReadChunkSize() { byte\[\] readChunkSize; readChunkSize = new byte\[4\]; \_memoryStream.Read(readChunkSize, 0, 3); return BitConverter.ToInt32(readChunkSize, 0); } }
`BinaryWriter.Write(string)` writes a length-preceded string to the stream, with the length encoded as a variable-length integer (7 bits per block and a continuation bit). So some extra stuff appeared in your stream that you didn't count on. `BinaryWriter.Write(string)` is most easily "mirrored" by using `BinaryReader.ReadString` in the decoder. Of course, you can also handle the length manually, but then you should probably also handle the encoding and write *raw bytes* to the stream to start with. This is also wrong: `_memoryStream.Read(readChunkSize, 0, 3);` reading 3 bytes instead of 4. Why not use `BinaryReader`, it's simpler and less error prone. By having written one extra byte per mistake (the extra length byte that `BinaryWriter.Write(string)` wrote, could have been more bytes for longer strings) and by having read one byte too few, a two byte discrepancy was created. Actually you should find that there are two unprintable characters at the start of your string, since it still should be 12 bytes, just not quite the right 12 bytes.
-
`BinaryWriter.Write(string)` writes a length-preceded string to the stream, with the length encoded as a variable-length integer (7 bits per block and a continuation bit). So some extra stuff appeared in your stream that you didn't count on. `BinaryWriter.Write(string)` is most easily "mirrored" by using `BinaryReader.ReadString` in the decoder. Of course, you can also handle the length manually, but then you should probably also handle the encoding and write *raw bytes* to the stream to start with. This is also wrong: `_memoryStream.Read(readChunkSize, 0, 3);` reading 3 bytes instead of 4. Why not use `BinaryReader`, it's simpler and less error prone. By having written one extra byte per mistake (the extra length byte that `BinaryWriter.Write(string)` wrote, could have been more bytes for longer strings) and by having read one byte too few, a two byte discrepancy was created. Actually you should find that there are two unprintable characters at the start of your string, since it still should be 12 bytes, just not quite the right 12 bytes.
sure enough _memoryStream.Read(readChunkSize, 0, 4); fixed part of the problem and also changing the Write message as below fixed the issue. but I want to use BinaryReader since I'm using BinaryWriter the behavior I'm seeing is I can consecutively call ReadByte and it will read each byte in turn without me having to define position within the stream, which I don't understand. so how do is use BinaryReader to read specific blocks of bytes, 2->6, and 7->19 thanks Madaxe
public void WriteMessage(string message)
{
WriteNextChunckSize(message.Length);
byte[] byteArray = Encoding.UTF8.GetBytes(message);
BinaryWriter.Write(byteArray);
} -
sure enough _memoryStream.Read(readChunkSize, 0, 4); fixed part of the problem and also changing the Write message as below fixed the issue. but I want to use BinaryReader since I'm using BinaryWriter the behavior I'm seeing is I can consecutively call ReadByte and it will read each byte in turn without me having to define position within the stream, which I don't understand. so how do is use BinaryReader to read specific blocks of bytes, 2->6, and 7->19 thanks Madaxe
public void WriteMessage(string message)
{
WriteNextChunckSize(message.Length);
byte[] byteArray = Encoding.UTF8.GetBytes(message);
BinaryWriter.Write(byteArray);
}You can do some dummy reads of suitable sizes, discard the results, and then call the suitable Read method when the position of the stream is at the intended location. Or you can set the position of the underlying stream directly, and then read with the BinaryReader. Unfortunately both of these feel a bit like a hack, IMO there should have been some method on BinaryReader to skip a number of bytes, but that doesn't exist.