开发者

How do you call this binary data type, and how to handle it in C#?

Let's say we have a binary file that contains 2 bytes that form an integer, in reverse.

So for example, the bytes show like this: (hexadecimal)

EB 03 00 00

Which should be interpreted as this:

00 00 03 EB

Which C# should be able to input as decimal 1003. Is this possible if you have the EB and 03 bytes already in memory in 2 different variables? Is there some math I can apply here to form decimal 1003 from the numbers 235 and 3? Or should I do it completely different?

Thanks 开发者_JAVA技巧in advance!


What you talk about is called Endianness, in particular Little Endian format.

In C#, it's probably easiest to use a BinaryReader or BinaryWriter to read from binary files which wrap the correct conversion of the byte order.

The following sample shows how to use a BinaryReader to get the correct integer interpretation of a number in Little Endian format:

using System.IO;

class EndiannessSample
{
    static void Main(string[] args)
    {
        using (MemoryStream ms = new MemoryStream())
        {
            // write bytes in little-endian format
            ms.WriteByte(0xEB);
            ms.WriteByte(0x03);
            ms.WriteByte(0x00);
            ms.WriteByte(0x00);
            ms.Position = 0;

            using (BinaryReader reader = new BinaryReader(ms))
            {
                int i = reader.ReadInt32(); // decimal value of i is 1003
            }
        }
    }
}

Little endian is the standard on Intel (and Windows) platforms. In case you have to deal with data in Big Endian format (e.g. when importing files created on an old Macintosh) there is no direct support within .NET. You can write a simple utility function for converting endianness using the BitConverter class. In the sample above you could do the following to cope with Big Endian (on a Little Endian platform):

using (MemoryStream ms = new MemoryStream())
{
    // write bytes in big-endian format
    ms.WriteByte(0x00);
    ms.WriteByte(0x00);
    ms.WriteByte(0x03);
    ms.WriteByte(0xEB);
        
    ms.Position = 0;
    using (BinaryReader reader = new BinaryReader(ms))
    {
        byte[] temp = reader.ReadBytes(4);
        if (BitConverter.IsLittleEndian)
        {
            // reverse the byte order only if we are on a little-endian system,
            // because the BitConverter is aware of the endianness of the system
            //
            Array.Reverse(temp);
        }
        int i = BitConverter.ToInt32(temp, 0);
    }
}

LukeH provided a link that further discusses problems related to Endianness, e.g. when targeting Xbox 360 (which happens to be a Big Endian platform):

One Little, Two Little, Three Little Endian... 0x0A Big Endian Bugs

Update

The MiscUtil library provides a binary reader/writer class that can be configured for a specific Endianness:

MiscUtil.IO.EndianBinary{Writer/Reader}


You should be able to just read the value from the binary file into an unsigned 32 bit integer:

UInt32 myValue;

using this method from your BinaryReader object:

myValue = reader.ReadUInt32();

On a Little Endian system (i.e. Intel), the byte order will reverse automatically.

To get your array of bytes:

byte[] b = BitConverter.GetBytes(myValue);


Is this possible if you have the EB and 03 bytes already in memory in 2 different variables?

Yes...

byte x = 0xEB;
byte y = 0x03;

int i = (y << 8) | x;
// or
short s = (short)((y << 8) | x);

Or if you have four bytes that you want to convert to an int:

byte a = 0x01;
byte b = 0x02;  
byte c = 0x03;
byte d = 0x04;

int i = (a << 24) | (b << 16) | (c << 8) | d;
// or if you want to reverse the endianness...
int j = (d << 24) | (c << 16) | (b << 8) | a;


You could use the BitConverter class has Robert mentioned. A simple example:

     byte[] byte_arr = new byte[] { 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78, 0x89 };
     UInt16 uint1 = BitConverter.ToUInt16(byte_arr, 0); // 0x2312
     UInt16 uint2 = BitConverter.ToUInt16(byte_arr, 4); // 0x6756


This is called Little Endian and it’s the normal byte-order in Windows.

You can use BinaryReader to read integers from a stream in this form.

If you want to roll your own...

var b1 = file.ReadByte();
var b2 = file.ReadByte();
var b3 = file.ReadByte();
var b4 = file.ReadByte();
var result = b1 | (b2 << 8) | (b3 << 16) | (b4 << 24);

(Of course, in real code, check for premature end of file, etc.)

If you already have the data in a byte array:

byte[] b = ...;
var result = b[0] | (b[1] << 8) | (b[2] << 16) | (b[3] << 24);
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜