【问题标题】:How can I convert a hex string to a byte array? [duplicate]如何将十六进制字符串转换为字节数组? [复制]
【发布时间】:2010-09-24 04:43:15
【问题描述】:

我们可以使用 C# 中的内置函数将十六进制字符串转换为字节数组,还是我必须为此创建一个自定义方法?

【问题讨论】:

  • 您可以在一行中轻松地将字符串转换为字节[]:var byteArray = Encoding.ASCII.GetBytes(string_with_your_data);
  • @mik-T,十六进制字符串采用某种格式,例如 219098C10D7,每两个字符转换为一个字节。你的方法不可用。
  • 此问题似乎与所选问题不重复。这一个将 FROM 十六进制字符串转换为字节数组,但是其他问题将字节数组转换为十六进制。
  • 一个简单的单行代码:BigInteger.Parse(str, System.Globalization.NumberStyles.HexNumber).ToByteArray().Reverse().ToArray()
  • @GregoryMorse 请注意,BigInteger 假定字符串表示有符号数,如果 MSB 的最高有效位为 1,则会给出意外结果,除非您进行特殊处理。

标签: c# encoding hex


【解决方案1】:

这是一个有趣的 LINQ 示例。

public static byte[] StringToByteArray(string hex) {
    return Enumerable.Range(0, hex.Length)
                     .Where(x => x % 2 == 0)
                     .Select(x => Convert.ToByte(hex.Substring(x, 2), 16))
                     .ToArray();
}

【讨论】:

  • 天哪!!你知道这是多么的低效吗???当然,这很有趣,但是 LINQ 被过度使用于原本应该做的事情! LINQ 代码需要 .NET 3.5 并且需要引用 System.Core(否则可能不需要)。有关有效解决方案,请参阅重复文章。
  • 这可能是为了好玩,而不是高效
  • 对 LINQ 的优雅和多功能性印象深刻
  • 想出了这个去另一个方向。如果其他人需要它... public static string ByteArrayToBinHex( this byte[] bytes ) { return bytes.Select( b => b.ToString( "X2" ) ).Aggregate( ( s1, s2 ) => s1 + s2); }
  • 较短的版本是Enumerable.Range(0, hex.Length / 2) .Select(x => Convert.ToByte(hex.Substring(x * 2, 2), 16)) .ToArray()
【解决方案2】:

以下代码通过逐字节解析字符串将十六进制字符串更改为字节数组。

public static byte[] ConvertHexStringToByteArray(string hexString)
{
    if (hexString.Length % 2 != 0)
    {
        throw new ArgumentException(String.Format(CultureInfo.InvariantCulture, "The binary key cannot have an odd number of digits: {0}", hexString));
    }

    byte[] data = new byte[hexString.Length / 2];
    for (int index = 0; index < data.Length; index++)
    {
        string byteValue = hexString.Substring(index * 2, 2);
        data[index] = byte.Parse(byteValue, NumberStyles.HexNumber, CultureInfo.InvariantCulture);
    }

    return data; 
}

【讨论】:

  • 不应该是“for (int index = 0; index
  • 68016101061B4A60193390662046804020422044204000420040402060226024676DB16 有了这个我得到The binary key cannot have an odd number of digits
【解决方案3】:

我做了一些研究,发现 byte.Parse 比 Convert.ToByte 还要慢。 我能想到的最快转换使用大约每字节 15 个滴答声。

    public static byte[] StringToByteArrayFastest(string hex) {
        if (hex.Length % 2 == 1)
            throw new Exception("The binary key cannot have an odd number of digits");

        byte[] arr = new byte[hex.Length >> 1];

        for (int i = 0; i < hex.Length >> 1; ++i)
        {
            arr[i] = (byte)((GetHexVal(hex[i << 1]) << 4) + (GetHexVal(hex[(i << 1) + 1])));
        }

        return arr;
    }

    public static int GetHexVal(char hex) {
        int val = (int)hex;
        //For uppercase A-F letters:
        //return val - (val < 58 ? 48 : 55);
        //For lowercase a-f letters:
        //return val - (val < 58 ? 48 : 87);
        //Or the two combined, but a bit slower:
        return val - (val < 58 ? 48 : (val < 97 ? 55 : 87));
    }

// 也适用于 .NET Micro Framework,其中(在 SDK4.3 中)byte.Parse(string) 只允许整数格式。

【讨论】:

  • 我试过了,但不知何故这稍微快了一点。可能是因为堆和栈的区别。
  • 回答您需要了解很多关于编译器如何做出关于自动内联的决定
  • 字节与我这边的十六进制字符的顺序相同。反向是什么意思?
  • 我刚刚发现这段代码粘贴到我必须维护的程序中。它不再编译并抛出 CS0307(变量 'i' 不能与类型 args 一起使用)和 CS0118('hex' 是一个变量,但用作一种类型)。使用按位移位(而不是简单的旧“/ 2”)可能看起来很酷,但对于 99.99% 的开发人员来说,这是一个明显的过早优化邪恶案例。
  • @RobertSnyder - 我的观点与编译无关(尽管它在一夜之间或多或少地被破坏了,并且最近没有对构建服务器进行更改)。我们让顾问将此代码复制粘贴到不需要这种性能级别的程序中。 .
【解决方案4】:

我认为这可能有效。

public static byte[] StrToByteArray(string str)
    {
        Dictionary<string, byte> hexindex = new Dictionary<string, byte>();
        for (int i = 0; i <= 255; i++)
            hexindex.Add(i.ToString("X2"), (byte)i);

        List<byte> hexres = new List<byte>();
        for (int i = 0; i < str.Length; i += 2)            
            hexres.Add(hexindex[str.Substring(i, 2)]);

        return hexres.ToArray();
    }

【讨论】:

    猜你喜欢
    • 2018-05-09
    • 2011-02-27
    • 2017-08-23
    • 2013-01-14
    • 1970-01-01
    • 2021-10-31
    • 2019-02-12
    相关资源
    最近更新 更多