You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C# BitConverter转换首字节错误求助——遥测数据协议实现

解决C#遥测数据协议中BitConverter转换首字节错误问题

我正在为遥控车项目实现遥测数据通信协议,因为带宽紧张,需要把整数转换为最小尺寸的byte数组来缩减缓冲区大小。目前我的代码返回的字节列表除首个元素外其余都正确,尝试将long值拆分为最小适配类型后用BitConverter.GetBytes()转换,但首字节总是不符合预期。

原代码

using System;

public static class TelemetryBuffer
{
    public static byte[] ToBuffer(long a)
    {
        if (9223372036854775807 >= a && a > 4294967296)
        {
            long num = (long)a;
            byte[] bytes = new byte[8];
            bytes = BitConverter.GetBytes(num);
            return bytes;
        }
        else if (4294967296 >= a && a > 2147483648)
        {
            uint num = (uint)a;
            byte[] bytes = new byte[8];
            bytes = BitConverter.GetBytes(num);
            return bytes;
        }
        else if (2147483647 >= a && a > 65536)
        {
            int num = (int)a;
            byte[] bytes = new byte[8];
            bytes = BitConverter.GetBytes(num);
            return bytes;
        }
        else if (65535 >= a && a > 0)
        {
            ushort num = (ushort)a;
            byte[] bytes = new byte[8];
            bytes = BitConverter.GetBytes(num);
            return bytes;
        }
        else if (-1 >= a && a > -32768)
        {
            short num = (short)a;
            byte[] bytes = new byte[8];
            bytes = BitConverter.GetBytes(num);
            return bytes;
        }
        else if (-2147483648 < a && a <= -32769)
        {
            int num = (int)a;
            byte[] bytes = new byte[8];
            bytes = BitConverter.GetBytes(num);
            return bytes;
        }
        else if (-9_223_372_036_854_775_808 < a && a <= -2_147_483_649)
        {
            long num = (long)a;
            byte[] bytes = new byte[8];
            bytes = BitConverter.GetBytes(num);
            return bytes;
        }
        else
        {
            int num = (int)a;
            byte[] bytes = new byte[8];
            bytes = BitConverter.GetBytes(num);
            return bytes;
        }

        //throw new NotImplementedException("Please implement the static TelemetryBuffer.ToBuffer() method");
    }

    public static long FromBuffer(byte[] buffer)
    {
        throw new NotImplementedException("Please implement the static TelemetryBuffer.FromBuffer() method");
    }
}

断言失败示例

Assert.Equal() Failure
           ↓ (pos 0)
Expected: [248, 255, 255, 255, 255, ...]
Actual:   [255, 255, 255, 255, 255, ...]
           ↑ (pos 0)
Assert.Equal() Failure
           ↓ (pos 0)
Expected: [248, 0, 0, 0, 0, ...]
Actual:   [0, 0, 0, 0]
           ↑ (pos 0)
Assert.Equal() Failure
           ↓ (pos 0)
Expected: [4, 0, 0, 0, 128, ...]
Actual:   [0, 0, 0, 128]
           ↑ (pos 0)

问题根源

  • 缺少类型标识位:断言示例的首字节是协议规定的类型标记(比如248对应short类型,4对应int类型),但原代码直接返回BitConverter转换的原始字节,没有添加这个标识位。
  • 数组长度错误:比如ushort转换后应返回2字节数据+1字节标识共3字节,但原代码返回BitConverter的2字节数组,长度和预期不符。
  • 边界判断错误:硬编码的数值边界存在错误(比如a > 4294967296应该是a > uint.MaxValue),导致类型选择错误。

修复后的代码

using System;

public static class TelemetryBuffer
{
    // 根据断言示例定义类型标识位,需和协议约定一致
    private const byte Type_Int16 = 0xF8; // 对应示例中的248
    private const byte Type_Int32 = 0x04; // 对应示例中的4
    private const byte Type_Int64 = 0x08;
    private const byte Type_UInt16 = 0x02;
    private const byte Type_UInt32 = 0x05;

    public static byte[] ToBuffer(long a)
    {
        byte typeMarker;
        byte[] dataBytes;

        // 正数分支
        if (a > int.MaxValue)
        {
            if (a <= uint.MaxValue)
            {
                typeMarker = Type_UInt32;
                dataBytes = BitConverter.GetBytes((uint)a);
            }
            else
            {
                typeMarker = Type_Int64;
                dataBytes = BitConverter.GetBytes(a);
            }
        }
        else if (a > ushort.MaxValue)
        {
            typeMarker = Type_Int32;
            dataBytes = BitConverter.GetBytes((int)a);
        }
        else if (a > 0)
        {
            typeMarker = Type_UInt16;
            dataBytes = BitConverter.GetBytes((ushort)a);
        }
        // 负数分支
        else if (a >= short.MinValue)
        {
            typeMarker = Type_Int16;
            dataBytes = BitConverter.GetBytes((short)a);
        }
        else if (a >= int.MinValue)
        {
            typeMarker = Type_Int32;
            dataBytes = BitConverter.GetBytes((int)a);
        }
        else
        {
            typeMarker = Type_Int64;
            dataBytes = BitConverter.GetBytes(a);
        }

        // 构建结果数组:首字节是类型标识,后面是数据字节
        byte[] result = new byte[dataBytes.Length + 1];
        result[0] = typeMarker;
        Array.Copy(dataBytes, 0, result, 1, dataBytes.Length);
        return result;
    }

    public static long FromBuffer(byte[] buffer)
    {
        if (buffer == null || buffer.Length < 1)
            throw new ArgumentException("缓冲区无效");

        byte typeMarker = buffer[0];
        byte[] dataBytes = new byte[buffer.Length - 1];
        Array.Copy(buffer, 1, dataBytes, 0, dataBytes.Length);

        return typeMarker switch
        {
            Type_Int16 => BitConverter.ToInt16(dataBytes, 0),
            Type_Int32 => BitConverter.ToInt32(dataBytes, 0),
            Type_Int64 => BitConverter.ToInt64(dataBytes, 0),
            Type_UInt16 => BitConverter.ToUInt16(dataBytes, 0),
            Type_UInt32 => BitConverter.ToUInt32(dataBytes, 0),
            _ => throw new NotSupportedException("未知类型标识")
        };
    }
}

关键修复说明

  • 添加类型标识位:首字节用于标记后续数据的整数类型,和断言示例中的预期值对应(可根据实际协议调整标识位数值)。
  • 修正边界判断:使用.NET内置的int.MaxValue、ushort.MinValue等常量,避免硬编码数值错误。
  • 正确构建结果数组:将类型标识位放在数组首位,后续拼接转换后的原始数据,保证数组长度和结构符合协议要求。
  • 配套实现反向解析:完成FromBuffer方法,根据类型标识正确解析缓冲区数据。

内容的提问来源于stack exchange,提问作者DMMAHMOOD

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 05:13:13