如何将十六进制字符串转换为字节数组? [复制]

Posted

技术标签:

【中文标题】如何将十六进制字符串转换为字节数组? [复制]【英文标题】: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,则会给出意外结果,除非您进行特殊处理。 【参考方案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();
    

【讨论】:

以上是关于如何将十六进制字符串转换为字节数组? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

如何将普通字符串转换为等效的十六进制字节数组? [复制]

在 Java 中,如何将字节数组转换为十六进制数字字符串,同时保持前导零? [复制]

在 Java 中,如何将字节数组转换为十六进制数字字符串,同时保持前导零? [复制]

如何将字节数组转换为字符串? [复制]

如何将十六进制字符串转换为字节数组,以及十六进制字符串中的字节数组?

如何在 C++ 中将十六进制字符串转换为字节字符串? [复制]