2
\$\begingroup\$

I'm currently writing a binary reader that reads a value from a BinaryReader at a given position. For that I have to store the current position of the MemoryStream so I can restore it afterwards.

public byte GetByte(int position)
{
 long oldPosition = this.memoryStream.Position;
 this.memoryStream.Position = position;
 byte value = this.ReadByte();
 this.memoryStream.Position = oldPosition;
 return value;
}

EDIT: As requested, more similar functions:

public byte[] GetByteArray(int position, int length)
{
 long oldPosition = this.memoryStream.Position;
 this.memoryStream.Position = position;
 byte[] value = this.ReadByteArray(length);
 this.memoryStream.Position = oldPosition;
 return value;
}
public bool GetBoolean(int position)
{
 long oldPosition = this.memoryStream.Position;
 this.memoryStream.Position = position;
 bool value = this.ReadBoolean();
 this.memoryStream.Position = oldPosition;
 return value;
}
public ushort GetUInt16(int position)
{
 long oldPosition = this.memoryStream.Position;
 this.memoryStream.Position = position;
 ushort value = this.ReadUInt16();
 this.memoryStream.Position = oldPosition;
 return value;
}

and so on..

Is there any way to shorten this process and avoid doubled-code since I have many functions similar to that?

asked Apr 10, 2016 at 17:04
\$\endgroup\$
1
  • \$\begingroup\$ I'm conscious that neither your existing code, nor the code in Jesse's answer is thread-safe because of the use of Stream.Position. If you can be assured that it's only ever a MemoryStream that you'll be working with, you could produce a thread-safe implementation by working with the byte array (MemoryStream.GetBuffer()) and using BitConverter to read values. \$\endgroup\$ Commented Apr 15, 2016 at 0:06

1 Answer 1

3
\$\begingroup\$

Try a pair of methods like this:

public T GetValue<T>(int position, Func<T> readFunc)
{
 long oldPosition = this.memoryStream.Position;
 this.memoryStream.Position = position;
 T value = readFunc();
 this.memoryStream.Position = oldPosition;
 return value;
}
public T GetValue<T>(int position, Func<int, T> readFunc, int length)
{
 long oldPosition = this.memoryStream.Position;
 this.memoryStream.Position = position;
 T value = readFunc(length);
 this.memoryStream.Position = oldPosition;
 return value;
}

then they can be called as such:

byte b = GetValue(position, ReadByte);
byte[] ba = GetValue(position, ReadByteArray, length);
// etc.

ETA: I might write the methods like this to ensure the stream's position gets reset properly, even in the event of an exception:

public T GetValue<T>(int position, Func<T> readFunc)
{
 var oldPosition = this.memoryStream.Position;
 this.memoryStream.Position = position;
 try
 {
 return readFunc();
 }
 finally
 {
 this.memoryStream.Position = oldPosition;
 }
}
public T GetValue<T>(int position, Func<int, T> readFunc, int length)
{
 var oldPosition = this.memoryStream.Position;
 this.memoryStream.Position = position;
 try
 {
 return readFunc(length);
 }
 finally
 {
 this.memoryStream.Position = oldPosition;
 }
}
answered Apr 11, 2016 at 14:37
\$\endgroup\$
0

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.