C# 以小尾数方式从整数到字节的数组(通用函数)
我有这个方法可以将长字节数组转换成小字节数组C# 以小尾数方式从整数到字节的数组(通用函数),c#,C#,我有这个方法可以将长字节数组转换成小字节数组 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,
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);
如果我的机器是little endian,这就行了。
如果在big endian机器上运行,它也会工作吗?我想是的,但我想验证一下。我有同样的东西,我测试了它 我可以告诉你它100%有效。例如,如果你想亲自查看,你可以假装你需要它。因此,可以反转字节数组,如果它是
IsLittleEndian
,则反转它
在方法中,您的输出始终是
LittleEndian
,这正是您想要的。与位转换器类似。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个字节?您可以在IntPtr
和Marshal
的帮助下玩一个小把戏,以便转换任何结构(包括byte
、ushort
和ulong
):
编辑:问题中的实现有什么问题?(摘自评论)。
或者,重申这个问题,IntPtr
,Marshal
的内容是什么
问题实施的主要问题是初始转换为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;
}
// 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};
对于byte
和ulong
。如果您想将数值(byte
,short
,ulong
等)写入二进制文件,并将其传递到二进制流等,这种错误行为可能会导致问题:
使用(Stream stm=…){
...
字节[]缓冲区=无符号整数字节数组(…);
stm.Write(buffer,offset,buffer.Length);//如果你有一些包含多个字段的struct
,你不是必须反转每个字段而不是整个struct
吗?@PetSerAl:它将整个结构反转;因此在你当前的实现中,实现对任意struct
@quser:不是很有用(这是个问题)您将其转换为ulong
,因此,如果实际参数是Byte
,它将被视为ulong
,您将得到8项数组而不是1项数组是的,但这对我来说不是问题,那么我将只读取数组后面的第一个字节(我知道我首先向它传递了一个字节,对吗?)。还有其他问题吗?@quser:从技术上讲,您可以为字节
获取数组的第一项,或者说,为uint
获取数组的前4项,但这是一个容易出错的实现:您必须为方法的每次调用执行一个调用后过程。“如果您尝试使用单个方法检查零字节,则会产生错误的结果:如何判断数字00 00 12 34是否应反转2或4字节?“你能解释一下你在这里的意思吗?我用多种可能性测试了我的函数,它可以工作。如果我理解正确,你只有一个方法,你可以通过所有不同的类型(int,short,…)对于使用隐式强制转换的方法。该方法如何知道它必须反转多少字节?它将强制转换uint到ulong reverse long,并返回数组,请尝试将低值(例如1)传递给该方法。那么它将如何解释1为long,以小端方式从中获取字节数组,并返回结果。不是吗?
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};
using (Stream stm = ...) {
...
Byte[] buffer = UnsignedIntegerToLEByteArray(...);
stm.Write(buffer, offset, buffer.Length); // <- the (possibly!) erroneous write
...
}