【问题标题】:Converting string to equivalent byte hex in c#在c#中将字符串转换为等效的字节十六进制
【发布时间】:2020-09-03 13:01:01
【问题描述】:

我有一个传入字符串68016101061B4A60193390662046804020422044204000420040402060226024676DB16,我想转换为0x68 0x01 0x61 0x01 0x06 0x1B 0x4A 0x60 0x0B 0x86 0xE8 0x46 0x04 0x68 0x04 0x02 0x04 0x22 0x04 0x42 0x04 0x00 0x04 0x20 0x04 0x40 0x02 0x06 0x02, 0x26 0x02 0x46 0x76 0xDB 0x16,但以字节为单位。我想将这些字节写入串行端口。

port.Write(bytes, 0, bytes.Length);

更新 1

下面是我通过硬编码发送的字节数组

var dataItems = new byte[] { 0x68, 0x01, 0x61, 0x01, 0x06, 0x1B, 0x4A, 0x60, 0x0B, 0x86, 0xE8, 0x46, 0x04, 0x68, 0x04, 0x02,
            0x04, 0x22, 0x04, 0x42, 0x04, 0x00, 0x04, 0x20, 0x04, 0x40, 0x02, 0x06, 0x02, 0x26, 0x02, 0x46 ,0x76 ,0xDB ,0x16 };

它给了我下面的数组

如何转换?

【问题讨论】:

标签: c# .net string hex


【解决方案1】:

您可以使用正则表达式来执行此操作:

var regex = new Regex(@"(\d{2})");

string aString = "040204220442040004200404020602260246";
string replaced = regex.Replace(aString, "x$1 ");

Fiddle

编辑 似乎您需要字节而不是字符串,您可以使用此处建议的基于 Linq 的答案之一或简单循环:

if ((aString.Length % 2) != 0)
{
    // Handle invalid input
}

var bytes = new byte[aString.Length / 2];

int index = 0;
for (int i = 0; i < aString.Length; i += 2)
{
    string digits = aString.Substring(i, 2);
    byte aByte = (byte)int.Parse(digits, NumberStyles.HexNumber);

    bytes[index++] = aByte;
}

port.Write(bytes, 0, bytes.Length);

请注意,如果 GC 压力成为问题,您可以使用 ReadOnlySpan&lt;char&gt;

Fiddle

【讨论】:

  • 它在字符串中我想要它以字节为单位?
  • 输入可以是偶数和奇数
  • @Faisal 你什么意思?字节没有一致地序列化为 2 个字符?在这种情况下,无法解析您的字符串。例如,222 是指 [2, 2, 2]、[22, 2] 还是 [2, 22]?此外,查看第二个条目 (01) 似乎它们总是被序列化为 2 个字符。
  • 222 表示2,2,2
  • 我的完整字符串是68016101061B4A601933906620468040204220442040004200404020602260246046676DB16
【解决方案2】:

如果你想使用纯 LINQ,你可以做一些类似的事情

data
    .Select((x,i) => (Index: i, Value: x))
    .GroupBy(tuple => tuple.Index / 2, tuple => tuple.Value, (_,values) => "0x" + string.Join("",values))
    .Select(x => Convert.ToByte(x, 16))
    .ToArray();

如果你想要一个可笑的单线。

【讨论】:

  • 我想要它的十六进制字节。需要向某个端口发送数据
  • 改为转换为字节数组。
  • 那么哪个字节会减半?在示例12345 中,我期望0x01 0x23 0x450x12 0x34 0x50x12 0x34 0x50 的位。由于有奇数个半字节,并且没有解释如何处理那个奇怪的半字节,所以没有可靠的方法来回答您的问题。
  • 在我的问题中,6801 .....16,每个都是 1 个字节。所以68会变成0x6801变成0x01等等。
  • 是的,此解决方案适用于奇数字节。仍然会有偶数个字符,这是GroupBy关心的
【解决方案3】:

在 Linq 中:

string src = "040204220442040004200404020602260246";
string res = Enumerable.Range(0, src.Length)
                       .Where(i => i % 2 == 0)
                       .Aggregate<int, string, string>("", (s, i) => s + " 0x" + src.Substring(i, 2), (s) => s.Trim());

或 - 如果输入字符串很长 - 以提高性能:

 string res = Enumerable.Range(0, src.Length)
                        .Where(i => i % 2 == 0)
                        .Aggregate<int, StringBuilder, string>(new StringBuilder(), (sb, i) => sb.Append(" 0x").Append(src.Substring(i, 2)), (sb) => sb.ToString().Trim());

在这两种情况下,res 都包含 "0x04 0x02 0x04 0x22 0x04 0x42 0x04 0x00 0x04 0x20 0x04 0x04 0x02 0x06 0x02 0x26 0x02 0x46"

如果您希望将结果作为字节数组并处理具有奇数位数的输入字符串,则可以按以下方式完成:

string src = "040204220442040004200404020602260246";
if (src.Length % 2 == 1) src += "0";
byte[] res = Enumerable.Range(0, src.Length)
                       .Where(i => i % 2 == 0)
                       .Select(i => Byte.Parse(src.Substring(i, 2), System.Globalization.NumberStyles.AllowHexSpecifier))
                       .ToArray();

【讨论】:

  • 我得到奇数个值Index and length must refer to a location within the string. Parameter name: length
  • 如果输入字符串不包含偶数位数,您希望结果字符串是什么?根据您的期望,也可以修复 linq 表达式以支持该场景
  • 字符串可以是偶数也可以是奇数。
  • 如果您的输入字符串的奇数位数以 on 例如 7 结尾,您希望结果字符串中的最后一个元素是 0x07 或 0x70 还是简单的 0x7?
  • 如果您输入的字符串有奇数位数 - 例如:“98567”。您希望该字符串如何转换?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-01-31
  • 1970-01-01
  • 1970-01-01
  • 2017-06-17
  • 2023-03-07
  • 2022-06-18
  • 2017-08-23
相关资源
最近更新 更多