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
相关产品推荐
相关产品推荐

