如何使用bitConverter.ToInt32方法从c#中获取big endian的小端数据?

Dan*_*any 28 c# bytearray endianness

我在c#中进行应用程序.在该应用程序中,我有包含十六进制值的字节数组.

在这里,我将数据作为一个大端,但我希望它作为一个小端.

这里我使用的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);
Run Code Online (Sandbox Code Playgroud)

该转换还有其他方法吗?

All*_*n A 34

在现代的Linq中,单行且易于理解的版本将是:

int number = BitConverter.ToInt32(waveData.Skip(286).Take(4).Reverse().ToArray(), 0);
Run Code Online (Sandbox Code Playgroud)

你也可以......

byte[] tempForTimestamp = new byte[4];
Array.Copy(waveData, 287, tempForTimestamp, 0, 4);
Array.Reverse(tempForTimestamp);
int number = BitConverter.ToInt32(tempForTimestamp);
Run Code Online (Sandbox Code Playgroud)

:)

  • 如果没有`.ToArray()`,在`Reverse()`之后,第一种形式对我不起作用. (4认同)
  • 如果处理字节数组,Buffer.BlockCopy 比 Array.Copy 更好。 (2认同)
  • 对于如此简单的低级任务,使用 Linq 就 GC 而言是一种过度杀伤力。这会慢得多,并且会在堆上创建数百个垃圾字节。 (2认同)

Mar*_*ell 24

如果您知道数据是big-endian,也许只需手动执行:

int value = (buffer[i++] << 24) | (buffer[i++] << 16)
          | (buffer[i++] << 8) | buffer[i++];
Run Code Online (Sandbox Code Playgroud)

这也可以在任何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;
Run Code Online (Sandbox Code Playgroud)

我发现第一个更具可读性,并且没有分支/复杂代码,所以它也应该非常快.第二个也可能在某些平台上遇到问题(CPU已经在运行big-endian).

  • 'int value = x[i] | 不是吗?x[j] | x[k] | ]x[l];' 已经采用大端字节序了吗?我知道 BitConverter 假定为小端字节序,因此如果他要将结果传递给 BitConverter.ToInt32(tempForTimestamp, 0); ,则需要您的第一个示例 但如果他只想要 int 值,那么他不是不使用位移位吗??? (2认同)
  • @Goku "int = xxxx" 没有提到任何关于字节序的信息,并且`BitConverter` **不**假设小字节序;它假设 CPU-endian - 只是:您碰巧使用的是小端 CPU。Big-endian CPU 已经存在并且可以运行 .NET。如果你想检查:查询`BitConverter.IsLittleEndian` (2认同)

Her*_*man 19

添加对 System.Memory nuget 的引用并使用 BinaryPrimitives.ReverseEndianness()。

using System.Buffers.Binary;
number = BinaryPrimitives.ReverseEndianness(number);
Run Code Online (Sandbox Code Playgroud)

它支持有符号和无符号整数(字节/短/整数/长)。

  • 精美的答案 (2认同)
  • “BinaryPrimitives”应该始终是现代 .NET 的答案。 (2认同)

Geo*_*voy 15

最直接的方法是使用.NET Standard 2.1 中引入的BinaryPrimitives.ReadInt32BigEndian(ReadOnlySpan) 方法

var number = BinaryPrimitives.ReadInt32BigEndian(waveData[297..291]);
Run Code Online (Sandbox Code Playgroud)


Ioa*_*mas 11

干得好

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;
} 
Run Code Online (Sandbox Code Playgroud)


FRL*_*FRL 8

声明这个类:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

例如,使用按钮和多行文本框创建表单:

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...
Run Code Online (Sandbox Code Playgroud)