How to convert hex to byte array?

I copied and pasted this binary data from an SQL server, which I cannot execute at this time.

0xBAC893CAB8B7FE03C927417A2A3F6A60BD30FF35E250011CB25507EBFCD5223B 

How to convert it back to byte array in C #?

+7
c # bytearray
source share
8 answers

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.

+20
source share

Consider using the Framework class, which already provides the ability to perform hexadecimal conversion, such as XmlReader:

 public static byte[] HexToBytes(this string hexEncodedBytes, int start, int end) { int length = end - start; const string tagName = "hex"; string fakeXmlDocument = String.Format("<{1}>{0}</{1}>", hexEncodedBytes.Substring(start, length), tagName); var stream = new MemoryStream(Encoding.ASCII.GetBytes(fakeXmlDocument)); XmlReader reader = XmlReader.Create(stream, new XmlReaderSettings()); int hexLength = length / 2; byte[] result = new byte[hexLength]; reader.ReadStartElement(tagName); reader.ReadContentAsBinHex(result, 0, hexLength); return result; } 

using:

 string input = "0xBAC893CAB8B7FE03C927417A2A3F6A60BD30FF35E250011CB255"; byte[] bytes = input.HexToBytes(2, input.Length); 
+7
source share

Plain:

 string hexnum = "0000000F"; // Represents 15 int value = int.Parse(hexnum, System.Globalization.NumberStyles.HexNumber); 

All you need to remember is to make int divide the hexadecimal number into groups of 8 hexadecimal digits (the hexadecimal bit is 4 bits, and the CLR int type is 32 bits, hence 8 digits per int). There's also byte.Parse (), which works the same, but is transmitted in two hexadecimal digits at a time.

+3
source share

Something like that:

  public byte[] ParseHexString(string text) { if ((text.Length % 2) != 0) { throw new ArgumentException("Invalid length: " + text.Length); } if (text.StartsWith("0x", StringComparison.InvariantCultureIgnoreCase)) { text = text.Substring(2); } int arrayLength = text.Length / 2; byte[] byteArray = new byte[arrayLength]; for (int i = 0; i < arrayLength; i++) { byteArray[i] = byte.Parse(text.Substring(i*2, 2), NumberStyles.HexNumber); } return byteArray; } 
+3
source share

You need to change this a bit (for example, skip the first two characters), but it handles spaces in the line:

  /// <summary> /// Decodes a hex string, ignoring all non-hex characters, and stores /// the decodes series of bytes into the shared buffer. This returns /// the number of bytes that were decoded. /// <para>Hex characters are [0-9, af, AF].</para> /// </summary> /// <param name="hexString">String to parse into bytes.</param> /// <param name="buffer">Buffer into which to store the decoded binary data.</param> /// <returns>The number of bytes decoded.</returns> private static int DecodeHexIntoBuffer(string hexString, byte[] buffer) { int count = 0; bool haveFirst = false; bool haveSecond = false; char first = '0'; char second = '0'; for (int i = 0; i < hexString.Length; i++) { if (!haveFirst) { first = hexString[i]; haveFirst = char.IsLetterOrDigit(first); // we have to continue to the next iteration // or we will miss characters continue; } if (!haveSecond) { second = hexString[i]; haveSecond = char.IsLetterOrDigit(second); } if (haveFirst && haveSecond) { string hex = "" + first + second; byte nextByte; if (byte.TryParse(hex, NumberStyles.HexNumber, null, out nextByte)) { // store the decoded byte into the next slot of the buffer buffer[count++] = nextByte; } // reset the flags haveFirst = haveSecond = false; } } return count; } 
+1
source share

Slow but interesting way: D

 public static byte[] StringToByteArray(string hex) { hex = hex.Replace(" ", ""); hex = hex.Replace(":", ""); return Enumerable.Range(0, hex.Length) .Where(x => x % 2 == 0) .Select(x => Convert.ToByte(hex.Substring(x, 2), 16)) .ToArray(); } 

-jD

+1
source share

In fact, there is an easier way to convert two characters at a time to bytes:

  /// <summary> /// This will convert a hex-encoded string to byte data /// </summary> /// <param name="hexData">The hex-encoded string to convert</param> /// <returns>The bytes that make up the hex string</returns> public static byte[] FromHex(string hexData) { List<byte> data = new List<byte>(); string byteSet = string.Empty; int stringLen = hexData.Length; int length = 0; for (int i = 0; i < stringLen; i = i + 2) { length = (stringLen - i) > 1 ? 2 : 1; byteSet = hexData.Substring(i, length); // try and parse the data data.Add(Convert.ToByte(byteSet, 16 /*base*/)); } // next set return data.ToArray(); } 
0
source share

I use this for C #, from similar code in Java.

  private static char[] hexdigit = "0123456789abcdef".ToCharArray(); public static string hexlify(string argbuf) { int arglen = argbuf.Length; char[] argca = argbuf.ToCharArray (); StringBuilder retbuf = new StringBuilder(arglen * 2); for (int i = 0; i < arglen; i++) { char ch = argca[i]; retbuf.Append(hexdigit[(ch >> 4) & 0xF]); retbuf.Append(hexdigit[ch & 0xF]); } return retbuf.ToString(); } public static string unhexlify(string argbuf) { int arglen = argbuf.Length; if (arglen % 2 != 0) { throw new ArgumentOutOfRangeException ("Odd-length string"); } char[] argca = argbuf.ToCharArray (); StringBuilder retbuf = new StringBuilder(arglen / 2); for (int i = 0; i < arglen; i += 2) { int top = Convert.ToInt32 (argca[i].ToString (), 16); int bot = Convert.ToInt32 (argca[i + 1].ToString (), 16); if (top == -1 || bot == -1) { throw new ArgumentOutOfRangeException ("Non-hexadecimal digit found"); } retbuf.Append((char) ((top << 4) + bot)); } return retbuf.ToString(); } 
0
source share

All Articles