我有这种方法将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机器上运行它也会工作吗?我想是的,但我想验证一下。
答案 0 :(得分:3)
您可以在IntPtr
和Marshal
的帮助下播放技巧,以转换任何 struct (包括byte
,ushort
和ulong
):
// 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);
编辑:问题中的实施有什么问题? (来自评论)。
或者,重述问题,IntPtr
,Marshal
的内容是什么?
问题实施的主要问题是初始转换到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>} byte
和ulong
。如果您想要将数值(byte
,short
,ulong
等)写入二进制文件,这种不当行为可能会导致问题,将它们传递给二进制流等:
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个字节?