以小端方式整数到字节数组(泛型函数)

时间:2015-10-13 08:31:24

标签: c#

我有这种方法将long转换为小端字节数组

public static byte[] UnsignedIntegerToLEByteArray(ulong value)
{    
    // Value in bytes... in your system's endianness (let's say: little endian)
    byte[] bytes = BitConverter.GetBytes(value);

    // If it was big endian, reverse it
    if (!BitConverter.IsLittleEndian)
        Array.Reverse(bytes); 

    return bytes;
}

我的目标是将它用于短路数据类型,如int,short等。请参见此处:

byte a = 0xAA;
ushort b = 0xEEAA;
uint c = 0xAABBCCDD;
ulong d = 0xAABBCCDDAAAAAABB;
// If you passed short below, you are only interested
// in first two bytes of the array
byte []tmp = DppUtilities.UnsignedIntegerToLEByteArray(b);

如果我的机器是小端,这是有效的。 如果在big endian机器上运行它也会工作吗?我想是的,但我想验证一下。

3 个答案:

答案 0 :(得分:3)

您可以在IntPtrMarshal的帮助下播放技巧,以转换任何 struct (包括byteushortulong):

// Disclaimer: the structure will be reversed as a whole, not field by field
public static byte[] ToLEByteArray<T>(T value) where T: struct {
  int size = Marshal.SizeOf(typeof(T));
  byte[] bytes = new byte[size];

  IntPtr p = Marshal.AllocHGlobal(size);

  try {
    Marshal.StructureToPtr(value, p, true);
    Marshal.Copy(p, bytes, 0, size);
  }
  finally {
    Marshal.FreeHGlobal(p);
  }

  // If it was big endian, reverse it
  if (!BitConverter.IsLittleEndian)
    Array.Reverse(bytes);

  return bytes;
}

...

  Byte b = 123;
  ushort s = 123;
  ulong l = 123;

  Byte[] result_byte = ToLEByteArray(b);
  Byte[] result_ushort = ToLEByteArray(s);
  Byte[] result_ulong = ToLEByteArray(l);

...

  int i = 123456; 
  Byte[] result_int = ToLEByteArray(i);

编辑:问题中的实施有什么问题? (来自评论)。       或者,重述问题,IntPtrMarshal的内容是什么?

问题实施的主要问题是初始转换ulong

  // all the arguments will be converted to ulong 
  public static byte[] UnsignedIntegerToLEByteArray(ulong value)

为了说明问题,想象一下,我们有两个值

Byte  x = 0x12;               // 18
ulong u = 0x0000000000000012; // 18

,预期输出为

new byte[] {0x12};                      // for a single byte
new byte[] {0x12, 0, 0, 0, 0, 0, 0, 0}; // for 8 bytes, i.e. ulong 

然而,实际输出将是

new byte[] {0x12, 0, 0, 0, 0, 0, 0, 0};

{/ 1>} byteulong。如果您想要将数值(byteshortulong等)写入二进制文件,这种不当行为可能会导致问题,将它们传递给二进制流等:

  using (Stream stm = ...) {
    ...
    Byte[] buffer = UnsignedIntegerToLEByteArray(...);

    stm.Write(buffer, offset, buffer.Length); // <- the (possibly!) erroneous write
    ...
  }

答案 1 :(得分:0)

我有同样的事情,我测试了它。

我可以告诉你它100%有效。如果你想自己检查一下,你可以举个例子假装你需要它。所以你反转字节数组并反转它,如果它是IsLittleEndian

您的输出始终位于方法LittleEndian中,这正是您想要的。

答案 2 :(得分:0)

就像BitConverter.GetBytes有不同的重载一样,你应该采用相同的方式:

public static byte[] UnsignedIntegerToLEByteArray(ulong value) { ...
public static byte[] UnsignedIntegerToLEByteArray(int value) { ...
public static byte[] UnsignedIntegerToLEByteArray(short value) { ...

当你使用它时,编译器会选择正确的重载:

byte []tmp = DppUtilities.UnsignedIntegerToLEByteArray(b);

如果您尝试使用尝试检查零字节的单个方法执行此操作,则会产生错误的结果: 如何判断数字00 00 12 34是否应该反转2或4个字节?