You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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}");
        }
    }
}

代码解释

  1. 半字节缓存机制:用pendingNibble变量暂存未找到配对的半字节,当遇到下一个半字节时,将两者拼接为完整字节(高4位左移4位后与低4位做按位或运算)。
  2. 规则适配:
    • 带0x前缀的字符串,根据长度判断是半字节(1位)还是完整字节(2位)。
    • 无前缀字符串,按长度区分:单个字符视为半字节(0-9),多个字符视为十进制字节(0-255)。你可以根据实际需求修改这部分判断逻辑。
  3. 异常处理:加入了多种异常判断,避免无效输入导致崩溃,同时对半字节未配对的情况抛出明确错误。

针对你的例子的处理

你的输入数组{"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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 05:06:21