将字符串表示的字节序列(如"3A 7F"或"3A7F")转换为实际的16进制字节数组,是协议解析、数据解码和嵌入式通信中的常见需求。这一过程涉及字符解析、进制转换和内存操作,需要精确处理边界和格式变体。
一、核心认知:字符串字节与16进制字节数组的关系
| 概念 | 示例 | 说明 |
|---|
| 字符串字节 | "3A 7F"、"3A7F"、"0x3A 0x7F" | 人类可读的16进制文本表示 |
| 16进制字节数组 | new byte[] { 0x3A, 0x7F } | 内存中的实际二进制值 |
| 编码本质 | 字符’3’(51)、‘A’(65)、空格(32)等 | 需解析为数值再组合为字节 |
关键洞察:这是双重解码过程——先解析字符为数值,再编码为字节值。
二、输入格式分类与处理策略
| 特性 | 说明 |
|---|
| 长度 | 必须为偶数(2字符=1字节) |
| 字符集 | 0-9, A-F, a-f |
| 示例 | "3A7F" → 0x3A, 0x7F |
| 复杂度 | 需验证长度,处理简单 |
| 特性 | 说明 |
|---|
| 长度 | 任意,按空格分割 |
| 容错性 | 高,可处理不规则输入 |
| 示例 | "3A 7F" → 0x3A, 0x7F |
| 复杂度 | 需字符串分割,再解析每段 |
| 特性 | 说明 |
|---|
| 标记 | 0x前缀或\x转义 |
| 示例 | "0x3A 0x7F" → 0x3A, 0x7F |
| 复杂度 | 需前缀识别和去除,再解析 |
- 格式D:混合格式(“3A 7F (58 127)”)
| 特性 | 说明 |
|---|
| 内容 | 16进制+十进制注释 |
| 处理 | 需提取有效部分,忽略注释 |
| 示例 | "3A 7F"部分→0x3A, 0x7F |
三、代码实现
public static byte[] ConvertStringToBytes(String str)
{
List<byte> listBytes = new List<byte>();
string[] hexValuesSplit = str.Trim().Split(' ');
foreach (string hex in hexValuesSplit)
{
listBytes.Add(Convert.ToByte(hex, 16));
}
return listBytes.ToArray();
四、异常处理与健壮性
| 异常类型 | 触发条件 | 处理策略 |
|---|
FormatException | 含非16进制字符(G-Z等) | 跳过、替换或报错 |
ArgumentException | 奇数长度(无法成对) | 补前导零、截断或报错 |
OverflowException | 解析值>255(非单字节) | 限制为255或扩展为多字节 |
IndexOutOfRangeException | 数组越界 | 预分配容量检查 |
五、总结
核心原则:
- 格式识别优先:自动检测输入模式,降低使用门槛
- 防御性解析:白名单字符、范围验证、容量检查
- 性能分层:只有实测瓶颈处使用unsafe/Span
- 协议契约:16进制字符串是中间表示,明确与字节的映射规则
- 可逆性验证:关键数据确保编解码闭环一致