如何修正ParseLocation函数的字节序(Endianess)错误?
问题描述
我正在解析一些数据,现有ParseLocation函数可正常运行,但存在字节序(Endianess)错误。例如当字节数组为:
Dim bytes As Byte() = {3, 7}
时,我期望得到结果0x0307,实际却得到0x0703,更大的变量也存在同样问题。以下是该函数代码:
Function ParseLocation(data As Byte()) As Dictionary(Of String, Object) Dim datasheet As New Dictionary(Of String, Object)() ' 从buffer 'data'读取并赋值到'datasheet' datasheet("startBit") = BitConverter.ToUInt16(data, 0) datasheet("protocolLength") = data(2) datasheet("protocolNumber") = data(3) datasheet("fixTime") = data.Skip(4).Take(6).ToArray() ' 从位置4开始取6字节 datasheet("quantity") = data(10) datasheet("lat") = BitConverter.ToUInt32(data, 11) datasheet("lon") = BitConverter.ToUInt32(data, 15) datasheet("speed") = data(19) datasheet("course") = BitConverter.ToUInt16(data, 20) datasheet("mcc") = BitConverter.ToUInt16(data, 22) datasheet("mnc") = data(24) datasheet("lac") = BitConverter.ToUInt16(data, 25) datasheet("cellId") = Convert.ToInt32(BitConverter.ToString(data, 27, 3).Replace("-", ""), 16) datasheet("serialNr") = BitConverter.ToUInt16(data, 30) datasheet("errorCheck") = BitConverter.ToUInt16(data, 32) Return datasheet End Function
请问该如何修复这个字节序错误?
修复方案
问题核心是数据采用大端字节序(Big-Endian)存储,但BitConverter默认使用当前系统的字节序(通常为小端Little-Endian),导致转换时字节顺序被反转。以下是具体修复方法:
1. 封装大端字节序转换工具函数
先编写通用的大端转换函数,替代BitConverter的默认逻辑:
' 大端字节序转UInt16 Function BigEndianToUInt16(bytes As Byte(), offset As Integer) As UInt16 Dim segment = bytes.Skip(offset).Take(2).ToArray() If BitConverter.IsLittleEndian Then Array.Reverse(segment) End If Return BitConverter.ToUInt16(segment, 0) End Function ' 大端字节序转UInt32 Function BigEndianToUInt32(bytes As Byte(), offset As Integer) As UInt32 Dim segment = bytes.Skip(offset).Take(4).ToArray() If BitConverter.IsLittleEndian Then Array.Reverse(segment) End If Return BitConverter.ToUInt32(segment, 0) End Function ' 处理3字节的CellId(大端转Int32) Function BigEndian3BytesToInt32(bytes As Byte(), offset As Integer) As Integer ' 3字节大端数据补高位0,转为4字节大端后处理 Dim extendedBytes = New Byte() {0, bytes(offset), bytes(offset+1), bytes(offset+2)} If BitConverter.IsLittleEndian Then Array.Reverse(extendedBytes) End If Return BitConverter.ToInt32(extendedBytes, 0) End Function
2. 修改原函数使用大端转换逻辑
将原函数中所有多字节转换的代码替换为上述工具函数:
Function ParseLocation(data As Byte()) As Dictionary(Of String, Object) Dim datasheet As New Dictionary(Of String, Object)() datasheet("startBit") = BigEndianToUInt16(data, 0) datasheet("protocolLength") = data(2) datasheet("protocolNumber") = data(3) datasheet("fixTime") = data.Skip(4).Take(6).ToArray() datasheet("quantity") = data(10) datasheet("lat") = BigEndianToUInt32(data, 11) datasheet("lon") = BigEndianToUInt32(data, 15) datasheet("speed") = data(19) datasheet("course") = BigEndianToUInt16(data, 20) datasheet("mcc") = BigEndianToUInt16(data, 22) datasheet("mnc") = data(24) datasheet("lac") = BigEndianToUInt16(data, 25) datasheet("cellId") = BigEndian3BytesToInt32(data, 27) datasheet("serialNr") = BigEndianToUInt16(data, 30) datasheet("errorCheck") = BigEndianToUInt16(data, 32) Return datasheet End Function
关键说明
BitConverter.IsLittleEndian用于判断当前系统字节序,仅在小端系统下反转字节,保证代码跨系统兼容。- 针对3字节的
cellId,通过补高位0转为4字节大端数据后处理,避免直接字符串拼接导致的字节序错误。
内容的提问来源于stack exchange,提问作者E_Blue
相关产品推荐
相关产品推荐

