BinaryReader -- can it be forced to read a BigEndian stream

L

Laszlo Szijarto

Can BinaryReader be forced to read a stream, say a TCP/IP stream or memory
stream or even file stream in big endian order or do I have to write
something custom to reverse the byte order? So, for example, I'd like a
Windows client PC (native little endian) to be able to read a network stream
coming in as big endian. I want to be able to read a short for example
without worrying about flipping the bytes.

Thank you,
Laszlo
 
M

Morten Wennevik

Hi Laszlo,

The BinaryReader uses UTF-8 encoding by default. You can specify your own encoding by using the overloaded constructor.

BinaryReader br = new BinaryReader(binaryStream, System.Text.Encoding.BigEndianUnicode);

Happy coding!
Morten Wennevik [C# MVP]
 
L

Laszlo Szijarto

Thanks again. When I set the Encoding, does that work for non-text data
types. So, when I do a ReadUInt16, does it read them BigEndian? I'll give
it a try. Thank you.

Morten Wennevik said:
Hi Laszlo,

The BinaryReader uses UTF-8 encoding by default. You can specify your own
encoding by using the overloaded constructor.
BinaryReader br = new BinaryReader(binaryStream, System.Text.Encoding.BigEndianUnicode);

Happy coding!
Morten Wennevik [C# MVP]
 
J

Jon Skeet [C# MVP]

Morten Wennevik said:
The BinaryReader uses UTF-8 encoding by default. You can specify your
own encoding by using the overloaded constructor.

BinaryReader br = new BinaryReader(binaryStream,
System.Text.Encoding.BigEndianUnicode);

I believe the OP is talking about the various other calls to
BinaryReader: ReadInt16 etc, not reading strings.
 
J

Jon Skeet [C# MVP]

Laszlo Szijarto said:
Can BinaryReader be forced to read a stream, say a TCP/IP stream or memory
stream or even file stream in big endian order or do I have to write
something custom to reverse the byte order? So, for example, I'd like a
Windows client PC (native little endian) to be able to read a network stream
coming in as big endian. I want to be able to read a short for example
without worrying about flipping the bytes.

I don't believe there is any way of doing it with the current
BinaryReader. I've considered a few times writing a BitConverter and
BinaryReader where you can specify the endianness, but never got round
to it. Let me know if you'd particularly like it and I'll see what I
can do - no promises of delivery date though!
 
L

Laszlo Szijarto

Thank you, John,

I really appreciate it. I've actually started writing my own
BinaryReaderBE. I can read basic data types. I've also extended it so that
it can read arrays of more than just bytes (so, short[], ushort[], int[],
uint[]). And, finally, I've added a function which would allow you to read
a struct (or class) out of a binary stream. You pass it a System.Type
object and it uses reflection to populate the various members, returning an
object. You have to cast the returned object to whatever type you want, but
it works really well. I've also implemented this for the Little Endian
Binary Reader in that same class. Pretty simple to do, and, given that
Network Byte Order teds to be Big Endian and that we here at NASA use Big
Endian for most things (we use a lot of Motorola CPUs), I'm surprised that
Microsoft doesn't have a Big Endian binary reader.

Inside the BinaryReaderBE, I have a private method which takes a byte[] and
flips it. Inside the ReadInt16, method, then, it returns a short
reconstructed from the reversed byte[] throught the BitConverter.

Thanks very much for the offer of help,
Laszlo
 
J

Jon Skeet [C# MVP]

Laszlo Szijarto said:
I really appreciate it. I've actually started writing my own
BinaryReaderBE. I can read basic data types. I've also extended it so that
it can read arrays of more than just bytes (so, short[], ushort[], int[],
uint[]). And, finally, I've added a function which would allow you to read
a struct (or class) out of a binary stream. You pass it a System.Type
object and it uses reflection to populate the various members, returning an
object.

How does it know what order to populate the members in? The order it
comes back from the Type.GetProperties call (or whatever) isn't
specified, so you should be a bit wary.
You have to cast the returned object to whatever type you want, but
it works really well. I've also implemented this for the Little Endian
Binary Reader in that same class. Pretty simple to do, and, given that
Network Byte Order teds to be Big Endian and that we here at NASA use Big
Endian for most things (we use a lot of Motorola CPUs), I'm surprised that
Microsoft doesn't have a Big Endian binary reader.

Yes, it is a bit short-sighted.
Inside the BinaryReaderBE, I have a private method which takes a byte[] and
flips it. Inside the ReadInt16, method, then, it returns a short
reconstructed from the reversed byte[] throught the BitConverter.

Right. I thought of using that, but reckoned it would probably be
easier (and faster) to do the conversions myself within my own
BinaryReader. I'll let you know if I find time to work on my
EndianBitConverter and EndianBinaryReader/Writer classes.
 
L

Laszlo Szijarto

Jon Skeet said:
Laszlo Szijarto said:
I really appreciate it. I've actually started writing my own
BinaryReaderBE. I can read basic data types. I've also extended it so that
it can read arrays of more than just bytes (so, short[], ushort[], int[],
uint[]). And, finally, I've added a function which would allow you to read
a struct (or class) out of a binary stream. You pass it a System.Type
object and it uses reflection to populate the various members, returning an
object.

How does it know what order to populate the members in? The order it
comes back from the Type.GetProperties call (or whatever) isn't
specified, so you should be a bit wary.

I use reflection as in the code snippet below. I've used this approach
before. It seems to work well.

public object ReadStruct(Type type)
{
object objectStruct = Activator.CreateInstance(type);
foreach (FieldInfo fieldInfo in type.GetFields())
{
switch(fieldInfo.FieldType.ToString())
{
case "System.Byte":
fieldInfo.SetValue(objectStruct, ReadByte());
break;
... [rest of supported data types]
}
}

return objectStruct;
}

You would call it as follows.

BinaryReaderBE binaryReaderBE = new BinaryReaderBE([stream object]);
[ClassName] class =
([ClassName])binaryReaderBE.ReadStruct(typeof([ClassName]);
 
L

Laszlo Szijarto

I've never had any trouble with stuff being out of order except if I've
changed my struct mid stream. Then, for some reason, I have to delete all
the stuff in the "bin" directories and THEN recompile. Otherwise, the order
always seems to come back as listed in the Class (or struct) Definition.
 
J

Jon Skeet [C# MVP]

Laszlo Szijarto said:
I've never had any trouble with stuff being out of order except if I've
changed my struct mid stream. Then, for some reason, I have to delete all
the stuff in the "bin" directories and THEN recompile. Otherwise, the order
always seems to come back as listed in the Class (or struct) Definition.

Yes, it does *now* - but it's not guaranteed that it will in the
future. You're relying on the implementation of GetFields not changing,
and I suspect it's very likely that it will in the future.
 
F

Filip Strugar

Laszlo Szijarto said:
Yes, it does *now* - but it's not guaranteed that it will in the
future. You're relying on the implementation of GetFields not changing,
and I suspect it's very likely that it will in the future.

Could [StructLayout(LayoutKind.Sequential)] help with this?
 
L

Laszlo Szijarto

Hmmm. OK. Then how else would I do something like this. It really would
be helpful if I could read a struct / class out of a stream (like you can in
C++) without resorting to unsafe code and pointers.
 
L

Laszlo Szijarto

If that works, is there an equivalent for a class? Unfortunately, with a
struct, if you have an array of any kind, you can't specify how many in that
array, so my algorithm won't work, whereas with a class, you can go

public short[] shrt = new short[5];

Filip Strugar said:
Definition.

Yes, it does *now* - but it's not guaranteed that it will in the
future. You're relying on the implementation of GetFields not changing,
and I suspect it's very likely that it will in the future.

Could [StructLayout(LayoutKind.Sequential)] help with this?
 
J

Jon Skeet [C# MVP]

Filip Strugar said:
Could [StructLayout(LayoutKind.Sequential)] help with this?

It wouldn't guarantee the order fields are returned in, no. It
determines the order of the fields in memory, but that's different.
 
J

Jon Skeet [C# MVP]

Laszlo Szijarto said:
Hmmm. OK. Then how else would I do something like this. It really would
be helpful if I could read a struct / class out of a stream (like you can in
C++) without resorting to unsafe code and pointers.

Well, you could always sort the fields yourself, eg alphabetically.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top