How can I convert a hex string to a byte array?
我们可以使用C中的内置函数将十六进制字符串转换为字节数组吗?还是必须为此生成自定义方法?
- 您可以在一行中轻松地将字符串转换为byte[]:var bytearray=encoding.ascii.getbytes(字符串_with_your_data);
- @MIK-T,十六进制字符串的格式类似于219098C10D7,每两个字符转换为一个单字节。您的方法不可用。
- 此问题似乎与所选问题不重复。这一个将十六进制字符串转换为字节数组,而另一个问题将字节数组转换为十六进制。
下面是一个有趣的Linq示例。
1 2 3 4 5 6
| 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(否则可能不需要)。有关有效的解决方案,请参阅重复文章。
- 可能是为了好玩,而不是为了效率。
- 这个答案至少还有编译的额外好处。另一个未定义keyasbytes。
- 更高效、更优雅的IMO:Enumerable.Range(0, hex.Length/2) .Select(x => Byte.Parse(hex.Substring(2*x, 2), NumberStyles.HexNumber)) .ToArray();去掉where子句,使用Byte.Parse()。
- Linq的优雅和多才多艺一直给人留下深刻印象
- 想到这个去另一个方向。如果其他人需要它…public static string bytearraytobinhex(this byte[]bytes)返回bytes.select(b=>b.tostring("x2")).aggregate((s1,s2)=>s1+s2);
- 字节数组到十六进制字符串只是bitconverter.toString()。
- 较短的版本是,Enumerable.Range(0, hex.Length / 2) .Select(x => Convert.ToByte(hex.Substring(x * 2, 2), 16)) .ToArray()。
- 这个表演怎么样?
- @Albatroscafe此代码的性能可能与测试结果匹配;)
- 这是这个答案的vb.net版本,对于那些需要它的人:Public Shared Function StringToByteArray(hex As String) As Byte() Return Enumerable.Range(0, hex.Length).Where(Function(x) (x Mod 2) = 0).Select(Function(x) Convert.ToByte(hex.Substring(x, 2), 16)).ToArray() End Function。
- 更快的一行程序,无子字符串:可枚举。范围(0,tx.长度/2)。选择((x)=>char c1=tx[x*2];char c2=tx[x*2+1];返回(字节)((c1
- 更有趣的是public static string HexStrToBin(this string HexStr)
- @Kevinp.Rice:与下面的"快速"版本相反,这个版本更难理解,在最新版本的vs中编译不正确,也不适用于小写字母。它在很久以前就被复制粘贴到我们的代码库中,导致了一个严重而难以发现的错误。
我做了一些研究,发现byte.parse比convert.tobyte更慢。我能想到的最快的转换大约每字节使用15个滴答。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| 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)只允许整数格式。
- 如果改为内联gethexval函数,效果会更好。
- 我试过了,但不知怎么的,速度稍微快一点。可能是因为堆和堆栈之间的区别。
- 嗯,奇怪。我用vb.net 2.0(2010编译器)x86使用if()三元运算符测试了它,它的内联速度肯定更快。一般来说,IL操作符不应该比任何函数调用都快吗?
- 要回答这个问题,您需要了解很多关于编译器如何决定自动内联的知识。
- 这对我来说很好,但我认为在大多数情况下,您希望数组中的字节与字符串中的十六进制字符的顺序相同。我在stringtobytearrayFastest()中的RETURN语句之前添加了Array.Reverse(arr);来解决这个问题。
- 字节的顺序与我这边的十六进制字符相同。反向是什么意思?
- 可能想看看codeproject.com/tips/447938/&hellip;用一个表替换gethexval()应该快得多。
- 请注意,此方法不使用任何边界检查,因此如果传递像"\b\b"这样的非十六进制字符串,将得到错误的结果。
- 你为什么把十六进制长度移到右边?hex.Length >> 1
- @莫赫拉达右移1是2的除法。一个十六进制字符代表4位,每个字节需要8位,因此2个字符转换为一个字节。
- hex.Length & 1比hex.Length % 2快吗?
- 我刚发现这个代码被粘贴到了一个我必须维护的程序中。它不再编译并抛出CS0307(变量"i"不能与类型参数一起使用)和CS0118("hex"是变量,但用作类型)。使用按位移位(而不是简单的"2")可能看起来很酷,但对于99.99%的开发人员来说,这显然是过早优化的一个问题。
- @StingyJack的问题不在于编译器的代码。根据msdn操作顺序,代码有效。简单的测试是在vs2013中打开它(编译),在vs2015+中打开它,您将看到所说的bug。用括号括起来编译错误就消失了
- @Robertsnyder——我的观点不是关于编译(尽管它或多或少在一夜之间就被破坏了,并且没有对构建服务器进行最近的更改)。我们让一个顾问复制粘贴这个代码到一个不需要这个性能级别的程序中。.
- 我认为在表演上甚至没有区别。移位有什么问题?
- 出了点问题。"CC"(204)编码为"EC"(236)
以下代码通过逐字节分析字符串,将十六进制字符串更改为字节数组。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| 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
我想这可能有效。
1 2 3 4 5 6 7 8 9 10 11 12
| 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();
} |