c#中从hex到字节的大多数轻量级转换?

可能重复:
如何将字节数组转换为hex字符串,反之亦然?

我需要一种有效而快速的方法来进行这种转换。 我尝试过两种不同的方式,但对我来说效率不高。 对于具有大量数据的应用程序,是否有任何其他快速方法可以实时完成此操作?

public byte[] StringToByteArray(string hex) { return Enumerable.Range(0, hex.Length / 2).Select(x => Byte.Parse(hex.Substring(2 * x, 2), NumberStyles.HexNumber)).ToArray(); } 

上面的一个对我来说更有效率。

  public static byte[] stringTobyte(string hexString) { try { int bytesCount = (hexString.Length) / 2; byte[] bytes = new byte[bytesCount]; for (int x = 0; x < bytesCount; ++x) { bytes[x] = Convert.ToByte(hexString.Substring(x * 2, 2), 16); } return bytes; } catch { throw; } 

我从另一个问题中获取了基准测试代码,然后重新设计它来测试这里给出的hex到字节的方法:

 HexToBytesJon: 36979.7 average ticks (over 150 runs) HexToBytesJon2: 35886.4 average ticks (over 150 runs) HexToBytesJonCiC: 31230.2 average ticks (over 150 runs) HexToBytesJase: 15359.1 average ticks (over 150 runs) 

HexToBytesJon是Jon的第一个版本, HexToBytesJon2是第二个版本。 HexToBytesJonCiC是Jon的版本,带有CodesInChaos的建议代码。 HexToBytesJase是我的尝试,基于上述两种情况,但使用替代的nybble转换,避免错误检查和分支:

  public static byte[] HexToBytesJase(string hexString) { if ((hexString.Length & 1) != 0) { throw new ArgumentException("Input must have even number of characters"); } byte[] ret = new byte[hexString.Length/2]; for (int i = 0; i < ret.Length; i++) { int high = hexString[i*2]; int low = hexString[i*2+1]; high = (high & 0xf) + ((high & 0x40) >> 6) * 9; low = (low & 0xf) + ((low & 0x40) >> 6) * 9; ret[i] = (byte)((high << 4) | low); } return ret; } 

如果你真的需要效率那么:

  • 不要创建子串
  • 不要创建迭代器

或者,摆脱try块只有一个重新抛出的catch块,但为了简单而不是效率。

这将是一个非常有效的版本:

 public static byte[] ParseHex(string hexString) { if ((hexString.Length & 1) != 0) { throw new ArgumentException("Input must have even number of characters"); } int length = hexString.Length / 2; byte[] ret = new byte[length]; for (int i = 0, j = 0; i < length; i++) { int high = ParseNybble(hexString[j++]); int low = ParseNybble(hexString[j++]); ret[i] = (byte) ((high << 4) | low); } return ret; } private static int ParseNybble(char c) { // TODO: Benchmark using if statements instead switch (c) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': return c - '0'; case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': return c - ('a' - 10); case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': return c - ('A' - 10); default: throw new ArgumentException("Invalid nybble: " + c); } return c; } 

TODO指的是这样的替代方案。 我没有测量哪个更快。

 private static int ParseNybble(char c) { if (c >= '0' && c <= '9') { return c - '0'; } c = (char) (c & ~0x20); if (c >= 'A' && c <= 'F') { return c - ('A' - 10); } throw new ArgumentException("Invalid nybble: " + c); } 

作为Jon的基于ParseNybble的变体:

 public static byte[] ParseHex(string hexString) { if ((hexString.Length & 1) != 0) { throw new ArgumentException("Input must have even number of characters"); } byte[] ret = new byte[hexString.Length / 2]; for (int i = 0; i < ret.Length; i++) { int high = ParseNybble(hexString[i*2]); int low = ParseNybble(hexString[i*2+1]); ret[i] = (byte) ((high << 4) | low); } return ret; } private static int ParseNybble(char c) { unchecked { uint i = (uint)(c - '0'); if(i < 10) return (int)i; i = ((uint)c & ~0x20u) - 'A'; if(i < 6) return (int)i+10; throw new ArgumentException("Invalid nybble: " + c); } }