C# 从字节组装整数的效率更高

C# 从字节组装整数的效率更高,c#,C#,我的应用程序从串行端口接收数据,串行端口以数据包的形式发送。这些包定义如下 1 byte - Identifier 2 bytes - lenght of data n bytes - data 1 bytes - Checksum 例如,如果长度指定为508,则将有508字节,这将是127uint32\t值 目前,我使用以下代码从以字节形式发送的数据中汇编uint32\t值: private UInt32[] number_array = new UInt32[16384]; priv

我的应用程序从串行端口接收数据,串行端口以数据包的形式发送。这些包定义如下

1 byte  - Identifier
2 bytes - lenght of data
n bytes - data 
1 bytes - Checksum
例如,如果长度指定为
508
,则将有
508
字节,这将是
127
uint32\t

目前,我使用以下代码从以字节形式发送的数据中汇编
uint32\t
值:

private UInt32[] number_array = new UInt32[16384];

private void decodePacket(int startpos, byte[] data, int lenght)
{
    /* Starting position */
    int pos = startpos;

    for(int i=0; i<lenght; i++)
    {
        /* Convert 4 bytes to one uint32_t value */
        int value = data[i] | data[i + 1]<<8 | data[i + 2]<<16 | data[i + 3]<<24;
            
        /* Write to array */
        number_array[pos] = Convert.ToUInt32(value);

        /* Advance i by 4 (bytes */
        i += 4;

        /* Advance pos */
        pos++;
    }
}
private UInt32[]number_array=new UInt32[16384];
专用无效解码数据包(int startpos,字节[]数据,int长度)
{
/*起始位置*/
int pos=startpos;

对于(int i=0;i请看以下简单代码:

static void Main(string[] args)
{
    byte[] data = new byte[]
    {
        1, 10, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 5
    };

    byte id = data[0];
    byte[] len = new byte[4];
    Array.Copy(data, 1, len, 0, 2);

    int dataLen = BitConverter.ToInt32(len, 0);

    byte[] dataRead = new byte[dataLen];
    Array.Copy(data, 3, dataRead, 0, dataLen);

    byte checksum = data[data.Length - 1];

    Console.ReadKey();
}
现在,首先您得到第一个pos上的标识符。 接下来,您将获得数据的长度。您必须创建4字节数组以将值从数据数组复制到此新数组。它应该是4字节,因为您希望将这些字节转换为Int32。您可以将此数组的长度设置为2字节并将其转换为Int16,但Int32应该具有更好的性能

因此,当这个len数组中有长度数据时,可以将这些值转换为Int32。但是要小心endianes。它可能不同

最后创建一个包含所有真实数据的数组,然后将真实数据复制到新数组中


此解决方案应该比您的更快。但是…请注意持久性。

以下是使用C#

专用无效解码数据包(int startpos,字节[]数据,int长度)
{
/*起始位置*/
int pos=startpos;
对于(int i=0;i
这与讨论中的代码相同,但有两处更改

  • 索引
    i
    在两个位置递增,导致
    5
    的增量,而不是
    4
    。将其更改为
    4
    的一个增量
  • 使用
    BitConverter
    代替按位逻辑。虽然它可能不会提供任何显著的性能提升。为了平台独立性,最好使用
    BitConverter
  • 更新

    如果您的字节存储在32位对齐的内存地址
    位转换器
    为您提供最高性能转换。但在C#中,您无法保证内存位置对齐。在这种情况下,位移位是唯一的方法


    在位移位的情况下,
    bit converter
    也使用与前面所述相同的逻辑用于小端系统。但是,它可以通过为大端系统使用另一种位移位模式来帮助保持代码平台的独立性。

    甚至更好,因为您不必将
    int
    转换为
    uint
    。此外<代码> BitConverter 考虑使用连续的内存块来减少缓存丢失,加快数组的实际执行。您可以使用它。请注意:虽然数组中的字节顺序必须反映计算机系统架构的迂回性。“我认为它非常低效”。-与以往一样,不要猜测性能。为自己设定具体的要求,并进行衡量。您目前是否有这些要求,以及编写良好的基准测试?您当前的代码离满足这些要求有多近,您能否共享基准测试?我强烈怀疑此解决方案是否比最初的解决方案更有效。有绝对不需要分配
    len
    数组并复制字节。使用BitConverter.ToInt32中的第二个参数。当然需要。BitConverter.ToInt32需要4字节数组。这里的长度是2字节。无论如何,为什么要进行下表决?因为没有循环或迭代,所以效率更高。只需简单的内存y复制。@AdamJachocki您的代码没有将数据字节转换为
    int
    s,这是OP要求的更有效的方法。您只是将字节从一个数组复制到另一个数组。我不知道您为什么认为需要4字节数组。绝对不是这样。事实上,这就是为什么有第二个参数:指示位置在要读取的较长数组中。哦,要读取两字节整数,请使用(或手动位移位)。事实上,
    BitConverter
    依赖于平台:它使用基础平台的endianness。OP的原始代码,即使用手动位移位,以LSB顺序正确转换具有UINT的流,无论它在哪个平台上执行。@KrisVandermotten当您说“它使用基础平台的endianness”时这本身就意味着它是独立于平台的。Endianness应该用来决定是否必须向左或向右移动。
    private void decodePacket(int startpos, byte[] data, int lenght)
    {
        /* Starting position */
        int pos = startpos;
    
        for (int i = 0; i < lenght; i += 4)
        {
            /* Convert 4 bytes to one uint32_t value */
            int value = BitConverter.ToInt32(data, i);
    
            /* Write to array */
            number_array[pos] = Convert.ToUInt32(value);
    
            /* Advance pos */
            pos++;
        }
    }