如何使用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); }