PBS文件头CRC16校验不匹配求助:计算值与文件存储值不一致
PBS文件头CRC16校验不匹配求助:计算值与文件存储值不一致
问题描述
我正在开发一个C#项目,用于解析KRK系统使用的专有.pbs归档格式。文件头包含一个CRC16校验和,但我计算出的值始终和文件中存储的不匹配。
读取有效.pbs文件时,代码输出:
CRC check failed. Expected: 0xE3A2, Actual: 0x0506
文件头结构说明
.pbs文件以66字节的头部开头,具体布局如下:
- 0x00-0x01:签名(固定为"PB")
- 0x02-0x03:CRC16(uint16类型,存储的校验值)
- 0x04-0x41:元数据(包含版本、程序数量、各部分大小等,共62字节)
根据格式定义,CRC16应该是对**整个头部(排除CRC16字段本身)**计算得到的。
现有代码实现
主逻辑代码
var crc16 = new PBSTCRC16Calculator(); byte[] headerBytes = new byte[66]; stream.Read(headerBytes, 0, 66); // 提取排除CRC字段的头部数据(总长度64字节:2字节签名+62字节元数据) byte[] headerBytesWithoutCRC = new byte[64]; Array.Copy(headerBytes, 2, headerBytesWithoutCRC, 0, 64); crc16.Append(headerBytesWithoutCRC); ushort expected = BitConverter.ToUInt16(headerBytes, 2); ushort actual = (ushort)crc16.CRC; Console.WriteLine($"Expected: 0x{expected:X4}, Actual: 0x{actual:X4}");
初始CRC计算器类
public class PBSCRC16Calculator { private const ushort POLY = 0xA001; private ushort crc = 0xFFFF; public ushort CRC => crc; public void Append(byte[] data) { foreach (byte b in data) { crc ^= b; for (int i = 0; i < 8; i++) { if ((crc & 1) != 0) crc = (ushort)((crc >> 1) ^ POLY); else crc >>= 1; } } } }
尝试的查表版CRC计算器(含测试逻辑)
public class PBSCRC16Calculator { public short CRC { get; private set; } private readonly short[] crcTable = new short[256]; private readonly short cnCrc16 = -32763; public PBSCRC16Calculator() { for (short i = 0; (i & 0xFFFF) < 256; i++) { short data = (short)((i & 0xFFFF) << 8); short accum = 0; for (short j = 0; (j & 0xFFFF) < 8; j++) { if ((((data & 0xFFFF) ^ (accum & 0xFFFF)) & 0x8000) != 0) accum = (short)(((accum & 0xFFFF) << 1) ^ (cnCrc16 & 0xFFFF)); else accum = (short)((accum & 0xFFFF) << 1); data = (short)((data & 0xFFFF) << 1); } crcTable[i & 0xFF] = accum; } } public void Append(byte[] data) { short accum = 0; foreach (byte b in data) accum = (short)(crcTable[(b ^ (accum >> 8)) & 0xFF] ^ (accum << 8)); CRC = accum; } } class Program { static void Main() { var crc16 = new PBSCRC16Calculator(); byte[] headerBytes = new byte[66]; // 模拟示例头部数据 for (int i = 0; i < headerBytes.Length; i++) headerBytes[i] = (byte)(i + 1); // 提取排除CRC字段的头部数据 byte[] headerBytesWithoutCRC = new byte[64]; Array.Copy(headerBytes, 2, headerBytesWithoutCRC, 0, 64); crc16.Append(headerBytesWithoutCRC); ushort expected = BitConverter.ToUInt16(headerBytes, 2); ushort actual = (ushort)crc16.CRC; Console.WriteLine($"Expected: 0x{expected:X4}, Actual: 0x{actual:X4}"); } }
已尝试的排查方向
- 验证了字节序(通过
BitConverter.IsLittleEndian确认本地环境的字节序) - 尝试将CRC初始值改为
0x0000和0xFFFF两种情况 - 尝试反转整个头部的字节顺序后再计算
- 尝试过包含/排除CRC字段进行计算
但所有尝试得到的结果都和文件中存储的CRC值不匹配,希望能得到大家的排查思路或解决建议。




