Something like that:
using System; public static class Parser { static void Main() { string hex = "0xBAC893CAB8B7FE03C927417A2A3F6A6" + "0BD30FF35E250011CB25507EBFCD5223B"; byte[] parsed = ParseHex(hex); // Just for confirmation... Console.WriteLine(BitConverter.ToString(parsed)); } public static byte[] ParseHex(string hex) { int offset = hex.StartsWith("0x") ? 2 : 0; if ((hex.Length % 2) != 0) { throw new ArgumentException("Invalid length: " + hex.Length); } byte[] ret = new byte[(hex.Length-offset)/2]; for (int i=0; i < ret.Length; i++) { ret[i] = (byte) ((ParseNybble(hex[offset]) << 4) | ParseNybble(hex[offset+1])); offset += 2; } return ret; } static int ParseNybble(char c) { if (c >= '0' && c <= '9') { return c-'0'; } if (c >= 'A' && c <= 'F') { return c-'A'+10; } if (c >= 'a' && c <= 'f') { return c-'a'+10; } throw new ArgumentException("Invalid hex digit: " + c); } }
(EDIT: now a little more efficient - no substrings required ...)
It is possible that ParseNybble may be more efficient. For example, a switch / register may be more efficient:
static int ParseNybble(char c) { 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; } throw new ArgumentException("Invalid hex digit: " + c); }
or possibly a search array:
// Omitted for brevity... I'm sure you get the gist private static readonly int[] NybbleLookup = BuildLookup(); private int ParseNybble(char c) { if (c > 'f') { throw new ArgumentException("Invalid hex digit: " + c); } int ret = NybbleLookup[c]; if (ret == -1) { throw new ArgumentException("Invalid hex digit: " + c); } return ret; }
I did not compare any of them, and I have no idea what will be the fastest. However, the current solution is probably the easiest.
Jon skeet
source share