如何将十六进制字符串转换为字节数组? [复制]
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; index68016101061B4A60193390662046804020422044204000420040402060226024676DB16
有了这个我得到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 中,如何将字节数组转换为十六进制数字字符串,同时保持前导零? [复制]