C#中从字节与半字节构建字节数组及特定字符串数组转字节数组
在C#中从字节/半字节字符串构建字节数组的通用方案
看起来你需要处理混合了完整字节和半字节的字符串数组,核心难点是半字节的拼接逻辑。先明确我们要遵循的规则(结合你的描述整理):
- 半字节单元:带
0x前缀的单个十六进制字符(比如0x1、0x8),对应4位二进制值(0-15) - 字节单元:
- 无前缀的十进制数字(比如
5、7),直接解析为对应的字节值(0-255) - 带
0x前缀的两位十六进制字符串(比如0x66),解析为对应的字节值
- 无前缀的十进制数字(比如
对于半字节的拼接,通常逻辑是两个连续的半字节单元组合成一个完整字节,第一个半字节作为高4位,第二个作为低4位(比如0x1 + 0x8 → 0x18)。如果遇到半字节后跟字节的情况,需要先确认是否是输入异常,还是规则有特殊说明——不过根据你提到的要把0x1、5、0x8拼接成两个字节,推测这里的5其实是半字节(可能规则表述有小偏差),下面的通用方法会兼顾两种情况,让你可以灵活配置。
通用实现代码
下面是一个C#方法,支持自定义半字节判断规则,同时处理半字节拼接和字节直接转换:
using System; using System.Collections.Generic; public class ByteConverter { public static byte[] ConvertToByteArray(string[] content) { var result = new List<byte>(); int? pendingNibble = null; // 缓存未处理的半字节 foreach (var str in content) { if (str.StartsWith("0x", StringComparison.OrdinalIgnoreCase)) { var hexPart = str.Substring(2); if (hexPart.Length == 1) { // 解析半字节(0-15) if (int.TryParse(hexPart, System.Globalization.NumberStyles.HexNumber, null, out int nibble)) { if (pendingNibble.HasValue) { // 拼接两个半字节:高4位左移4位 + 低4位按位或 byte combinedByte = (byte)((pendingNibble.Value << 4) | nibble); result.Add(combinedByte); pendingNibble = null; } else { // 缓存当前半字节,等待配对 pendingNibble = nibble; } } else { throw new ArgumentException($"无效的半字节字符串:{str}"); } } else if (hexPart.Length == 2) { // 解析十六进制完整字节 if (byte.TryParse(hexPart, System.Globalization.NumberStyles.HexNumber, null, out byte b)) { // 若存在未处理的半字节,抛出异常(可根据需求修改逻辑) if (pendingNibble.HasValue) { throw new InvalidOperationException("半字节未完成拼接,遇到了完整字节"); } result.Add(b); } else { throw new ArgumentException($"无效的十六进制字节字符串:{str}"); } } else { throw new ArgumentException($"不支持的十六进制字符串长度:{str}"); } } else { // 处理无前缀数字:单个字符视为半字节,多个字符视为十进制字节 if (str.Length == 1) { if (int.TryParse(str, out int nibble) && nibble >= 0 && nibble <= 9) { if (pendingNibble.HasValue) { byte combinedByte = (byte)((pendingNibble.Value << 4) | nibble); result.Add(combinedByte); pendingNibble = null; } else { pendingNibble = nibble; } } else { throw new ArgumentException($"无效的半字节数字:{str}"); } } else { if (byte.TryParse(str, out byte b)) { if (pendingNibble.HasValue) { throw new InvalidOperationException("半字节未完成拼接,遇到了完整字节"); } result.Add(b); } else { throw new ArgumentException($"无效的十进制字节数字:{str}"); } } } } // 检查是否有未配对的半字节 if (pendingNibble.HasValue) { throw new InvalidOperationException("存在未完成拼接的半字节"); } return result.ToArray(); } // 测试你的输入例子 public static void Main() { string[] content = {"0x1", "5", "0x8", "7", "0x66"}; try { byte[] bytes = ConvertToByteArray(content); Console.WriteLine("转换后的字节数组:"); foreach (byte b in bytes) { Console.WriteLine($"0x{b:X2}"); } // 输出结果:0x15, 0x87, 0x66 } catch (Exception ex) { Console.WriteLine($"错误:{ex.Message}"); } } }
代码解释
- 半字节缓存机制:用
pendingNibble变量暂存未找到配对的半字节,当遇到下一个半字节时,将两者拼接为完整字节(高4位左移4位后与低4位做按位或运算)。 - 规则适配:
- 带
0x前缀的字符串,根据长度判断是半字节(1位)还是完整字节(2位)。 - 无前缀字符串,按长度区分:单个字符视为半字节(0-9),多个字符视为十进制字节(0-255)。你可以根据实际需求修改这部分判断逻辑。
- 带
- 异常处理:加入了多种异常判断,避免无效输入导致崩溃,同时对半字节未配对的情况抛出明确错误。
针对你的例子的处理
你的输入数组{"0x1", "5", "0x8", "7", "0x66"},按照代码规则处理:
0x1是半字节,进入缓存;5是半字节,与缓存的0x1拼接为0x15(十进制21);0x8是半字节,进入缓存;7是半字节,与缓存的0x8拼接为0x87(十进制135);0x66是完整字节,直接加入结果;
最终得到的字节数组是[0x15, 0x87, 0x66],对应十进制[21, 135, 102]。
如果你的实际规则中5是完整字节(而非半字节),代码会抛出异常,因为缓存的0x1半字节没有找到配对项。这种情况下你需要确认输入规则是否要求半字节必须成对出现,或者是否有其他拼接逻辑(比如半字节与字节低4位组合等),只需修改代码对应部分即可。
内容的提问来源于stack exchange,提问作者PythonNoob
相关产品推荐
相关产品推荐

