如何使用bitConverter.ToInt32方法从c#中获取big endian的小端数据?
我在c#中进行应用程序。在该应用程序中,我有包含hex值的字节数组。
在这里,我将数据作为一个大端,但我希望它作为一个小端。
这里我使用Bitconverter.toInt32
方法将该值转换为整数。
但我的问题是,在转换值之前,我必须将该4字节数据从源字节数组复制到临时数组中,然后反转该临时字节数组。
我不能反转源数组,因为它也包含其他数据。
因为我的应用程序变得缓慢。 代码这里我有一个字节的源数组作为waveData []。它包含很多数据。
byte[] tempForTimestamp=new byte[4]; tempForTimestamp[0] = waveData[290]; tempForTimestamp[1] = waveData[289]; tempForTimestamp[2] = waveData[288]; tempForTimestamp[3] = waveData[287]; int number = BitConverter.ToInt32(tempForTimestamp, 0);
该转换还有其他方法吗?
如果您知道数据是big-endian,也许只需手动执行:
int value = (buffer[i++] << 24) | (buffer[i++] << 16) | (buffer[i++] << 8) | buffer[i++];
这也可以在任何CPU上可靠地工作。 注意i
是您当前到缓冲区的偏移量。
另一种方法是洗牌:
byte tmp = buffer[i+3]; buffer[i+3] = buffer[i]; buffer[i] = tmp; tmp = buffer[i+2]; buffer[i+2] = buffer[i+1]; buffer[i+1] = tmp; int value = BitConverter.ToInt32(buffer, i); i += 4;
我发现第一个更具可读性,并且没有分支/复杂代码,所以它也应该非常快。 第二个也可能在某些平台上遇到问题(CPU已经在运行big-endian)。
在现代的Linq中,单行且易于理解的版本将是:
int number = BitConverter.ToInt32(waveData.Skip(286).Take(4).Reverse().ToArray(), 0);
你也可以……
byte[] tempForTimestamp = new byte[4]; Array.Copy(waveData, 287, tempForTimestamp, 0, 4); Array.Reverse(tempForTimestamp); int number = BitConverter.ToInt32(tempForTimestamp);
🙂
干得好
public static int SwapEndianness(int value) { var b1 = (value >> 0) & 0xff; var b2 = (value >> 8) & 0xff; var b3 = (value >> 16) & 0xff; var b4 = (value >> 24) & 0xff; return b1 << 24 | b2 << 16 | b3 << 8 | b4 << 0; }
声明这个类:
using static System.Net.IPAddress; namespace BigEndianExtension { public static class BigEndian { public static short ToBigEndian(this short value) => HostToNetworkOrder(value); public static int ToBigEndian(this int value) => HostToNetworkOrder(value); public static long ToBigEndian(this long value) => HostToNetworkOrder(value); public static short FromBigEndian(this short value) => NetworkToHostOrder(value); public static int FromBigEndian(this int value) => NetworkToHostOrder(value); public static long FromBigEndian(this long value) => NetworkToHostOrder(value); } }
例如,使用按钮和多行文本框创建表单:
using BigEndianExtension; private void button1_Click(object sender, EventArgs e) { short int16 = 0x1234; int int32 = 0x12345678; long int64 = 0x123456789abcdef0; string text = string.Format("LE:{0:X4}\r\nBE:{1:X4}\r\n", int16, int16.ToBigEndian()); text += string.Format("LE:{0:X8}\r\nBE:{1:X8}\r\n", int32, int32.ToBigEndian()); text += string.Format("LE:{0:X16}\r\nBE:{1:X16}\r\n", int64, int64.ToBigEndian()); textBox1.Text = text; } //Some code...
如果你不再需要那个反向的临时数组,你可以在传递参数时创建它,而不是进行四次赋值。 例如:
int i = 287; int value = BitConverter.ToInt32({ waveData(i + 3), waveData(i + 2), waveData(i + 1), waveData(i) }, 0);
添加对System.Memory nuget的引用,并使用BinaryPrimitives.ReverseEndianness()。
using System.Buffers.Binary; number = BinaryPrimitives.ReverseEndianness(number);
它支持有符号和无符号整数(byte / short / int / long)。
我使用以下辅助函数
public static Int16 ToInt16(byte[] data, int offset) { if (BitConverter.IsLittleEndian) return BitConverter.ToInt16(BitConverter.IsLittleEndian ? data.Skip(offset).Take(2).Reverse().ToArray() : data, 0); return BitConverter.ToInt16(data, offset); } public static Int32 ToInt32(byte[] data, int offset) { if (BitConverter.IsLittleEndian) return BitConverter.ToInt32(BitConverter.IsLittleEndian ? data.Skip(offset).Take(4).Reverse().ToArray() : data, 0); return BitConverter.ToInt32(data, offset); } public static Int64 ToInt64(byte[] data, int offset) { if (BitConverter.IsLittleEndian) return BitConverter.ToInt64(BitConverter.IsLittleEndian ? data.Skip(offset).Take(8).Reverse().ToArray() : data, 0); return BitConverter.ToInt64(data, offset); }