views:

76

answers:

2

I have a stream of bytes which contains a flag which identifies the endianness of the data in the header. I want to read the doubles from the stream, which will presumably need to be different if the endianness of the data in the header is different?

I am currently using a BinaryReader and calling ReadDouble to read the data from the stream, but if the endianness flag indicates that the data stream has a different endianness than the machine architecture then presumably this will not work?

How should this be handled? Should I check the endianness of my data against that of the current machine then when I want to read a double instead read the bytes raw into a byte array and do array.Reverse to reverse the data before using BitConverter.ToDouble () with the reversed data and a zero offset?

I could just test this but I do not have a source of data for both endianness so am a bit concerned about creating test data to test the parsing and this being different from what 'real' data might look like.

+1  A: 

if the endianness flag indicates that the data stream has a different endianness than the machine architecture then presumably this will not work?

First - the bit order is abstracted from you. Unless you are twiddling bits, you don't care.

The byte order is a different thing. For a 4-byte quantity, it can be least-significant-byte first or most-significant-byte first. I don't know what the ReadDouble() uses, but if you are using a BinaryReader on one end of the wire and a BinaryWriter on the other, then once again, you don't care. It should be written in the same order as it is read, without regard for endianness.

The only case where you care, it seems to me, is if you don't use .NET on the other end of the wire. In that case you must make sure that the bytes are in the proper order, using a scheme similar to what you described. (Array.Reverse, etc).

Normally applications that face this problem use a multi-byte signature to indicate clearly the order. In other words, write 0x01020304 to the stream, and on the reader side, if you get 0x04030201, you know you've got a difference in endianness.

I could just test this but I do not have a source of data for both endianness ...

Well you have to fix that. You can't develop without a capability to test what you're developing. It also begs the question: if you don't have a source that would use different endianness, then why are you worried about the issue at all?

See also:
- http://stackoverflow.com/questions/2003380/net-reversing-byte-order
- A class for choosing the endianness of BitConverter

Cheeso
I have a specification that states the format. I only have one example of an implementation (so only one example of endianness in my data), but the code must deal with the data in which ever format. I am not using .net on both ends. indeed all in know is that I have a byte[] as input and I need to parse it to extract the data from the array. The first part of the array is a header which contains, amongst other info, the byte order of the encoded data.
Sam Holder
ok, so do this: in your app, convert a constant byte array value (eg, `{0xFF, 0xFE, 0x01, 0x02}`) to an Int32 value. Then, do the same with the byte array you received from the actual data stream. Compare them. If they are the same, then the endianness is the same. If different, then you know you need to reverse. Then, use the class for choosing the endianness, linked in the answer above, as appropriate. That should work.
Cheeso
Thanks. i can check the endianness of the machine, or at least the endianness that the framework is going to use (BitConverter.IsLittleEndian), I really wanted confirmation that reversing the bytes using Array.Reverse and than passing these to the BitConverter.ToDouble() method was the right way forward if the endianness was not the same.
Sam Holder
Yes, Array.Reverse is correct. The reverse needs to be done in chunks, obviously. And the size of the chunk (number of bytes) depends on the size of the individual datum being read.
Cheeso
A: 

BinaryReader reads data (including doubles) in little endian :

BinaryReader..::.ReadDouble

BinaryReader reads this data type in little-endian format.

If you want to read BigEndian data, you may override BinaryReader methods or add overloads with an enum argument to specify the expected endianness.

To implement bing endian reading, you may look at Cheeso answer or do some reverse engeneering.

Guillaume