|

Introduction
While the .NET framework provides methods to convert a byte array into a Hexadecimal string ( byte.ToString(“X”) ), it is not so easy to convert a hexadecimal string back into a byte array. Such a function is useful when you need to backup data from your application on paper, such as an encryption key, and later, convert it back into data after the user types it in.
The HexEncoding class provided here, contains functions which allow for the conversion of a string in hexadecimal format into a byte array, and back. It also contains functions which lets you check the formatting of the string before conversion, and how many bytes a given string will produce.
Background
In a hexadecimal string, one byte is represented two hexadecimal characters. A hexadecimal character has a value of (A-F, 0-9).
e.g. string “01FFA0” is equivalent to byte[] { 1, 255, 160 }
Using the code
HexEncoding is the name of the class I created with static functions for hexadecimal string conversion.
Here’s a sample of how it is used, when the Convert button is clicked like on the screenshot: private void button1_Click(object sender, System.EventArgs e)
{
string hexString = txtHex.Text;
int discarded;
txtByteCount.Text = ((int)HexEncoding.GetByteCount(hexString)).ToString();
txtLength.Text = hexString.Length.ToString();
byte[] byteArray = HexEncoding.GetBytes(hexString, out discarded);
txtDiscard.Text = discarded.ToString();
string temp = "";
for (int i=0; i<byteArray.Length; i++)
{
temp += byteArray[i].ToString("D3") + " ";
}
txtByte.Text = temp;
txtHex2.Text = HexEncoding.ToString(byteArray);
}
HexEncoding.GetByteCount(string hexString) returns the number of bytes that will be generated from the hexString.
HexEncoding.GetBytes(string hexString, out int discarded) returns the byte array converted from the hexString, and the second parameter returns the number of non-hexadecimal characters that were ignored in the string. This includes dashes, whitespace, and letters after ‘F’.
HexEncoding.ToString(byte[]) returns the newly converted byte array back into string form. Notice the ‘-‘ characters are now missing.
The key function provided by the framework to convert a hexadecimal string to a single byte is this:
where “hex” is of the form “1A”, “00”, “FF”, etc.
Thanks to Polux on the .NET 247 newsgroups who posted the int.Parse(...) answer to another hexadecimal question.
| You must Sign In to use this message board. |
|
| | Msgs 1 to 25 of 57 (Total in Forum: 57) (Refresh) | FirstPrevNext |
|
|
 |
|
|
 |
|
|
 |
|
|
What about the speed and simplicity of my function :
private Byte[] hexStringToByteArray(string hexinput) { if (hexinput == String.Empty) return null; if (hexinput.Length % 2 == 1) hexinput = "0" + hexinput; int arr_size = hexinput.Length / 2; Byte[] myBytes = new Byte[arr_size]; for (int i = 0; i < arr_size; i++) myBytes[i] = Convert.ToByte(hexinput.Substring(i * 2, 2), 16); return myBytes; }
private void test() { string hex = "15900fF654654651516ABCDEFFF"; byte[] res = this.hexStringToByteArray(hex); string disp = String.Empty; foreach (byte b in res) disp += b.ToString("X2") + " - " + b.ToString() + Environment.NewLine; MessageBox.Show(disp); }
"Nothing happens unless first a dream...", Carl Sandburg
-- modified at 7:14 Monday 12th November, 2007
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
your source code was inspirational in my project.. i solved my problem, about from stringHex to byte array.. later that a great many fight.. and i find what is problem.. when i was encrypt my data :
public string WriteHex(byte[] array) { string from_array=null;
for (int i = 0; i < array.Length; i++) from_array+=array[i].ToString("X"); /* there is single X, its wrong! that's right from_array+=array[i].ToString("X2"); .... */ return from_array; }
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
 |
|
|
 |
|
|
 |
|
|
Exactly. Here is an example of a function that does return a byte[] using this method.
private static byte[] HexToData(string hexString) { if (hexString == null) return null;
if (hexString.Length % 2 == 1) hexString = '0' + hexString; // Up to you whether to pad the first or last byte
byte[] data = new byte[hexString.Length / 2];
for (int i = 0; i < data.Length; i++) data[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);
return data; }
It is better to use this than the code from the article.
Edit: Changed byte.Parse(string, System.Globalization.NumberStyles.HexNumber) to Convert.ToByte(string, 16). This gives about a 60% to 65% performance increase to the entire method.
modified on Wednesday, April 16, 2008 11:18 AM
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
What about the code:
//Create an array of bytes System.Security.Cryptography.RNGCryptoServiceProvider rng = new System.Security.Cryptography.RNGCryptoServiceProvider(); byte[] key = new byte[1024]; rng.GetNonZeroBytes(key);
//Convert to string - a one-liner no-brainer...  string ba_as_string = BitConverter.ToString(key); //Get rid of the annoying '-' and get the byte array back string[] hexaInfo = ba_as_string.Split('-'); System.Collections.ArrayList ba1 = new System.Collections.ArrayList(); foreach (string hexa in hexaInfo) ba1.Add(Convert.ToByte(hexa, 16)); byte[] ba2 = (byte[])ba1.ToArray(typeof(byte));
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
|
|
This does not do what it says on the tin, i.e. convert a string into a byte[]. This generates a sequence of bytes, converts them to a string, splits them into a string[] and then individually converts them. This would be useful if and only if you are passing in a string of the format FF-FF-...-FF (imagine that ba_as_string is an argument rather than generated inside the method and ba2 is returned from the method). The vast majority of cases will use the format FFFF...FF or 0xFFFF...FF.
However, after some testing I have found that Convert.ToByte is significantly faster than byte.Parse so I have modified my previous post to use this method. This allows my method to accept FFFF...FF format and, of course, if it is 0xFFFF...FF format, you can just cut off the 0x as you pass the hex string into the method. This cut execution time on 1 million iterations of a 116 character string from an average of 8.237 seconds to an average of 4.961 seconds on my machine, which is approximately 65% faster.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Hi,
I don't know if I totally agree with you on the format argument... probably it would be more frequent to see stuff like 0xFF-0xFF... and so forth...
No matter, we are discussing small potatoes here, the point was that this is not really a *big* problem and there are several ways to, so to say, "kill the rabbit"... 
For example, the following reduces the "for" cycle by half:
string ba_as_string_canonical = ba_as_string.Replace("-", string.Empty);
byte[] ba3 = new byte[ba_as_string_canonical.Length / 2]; for (int i = 0; i < ba_as_string_canonical.Length; i+=2 ) ba3[i/2] = Convert.ToByte(ba_as_string_canonical.Substring(i, 2), 16);
Thanks!
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
I have never seen it stored in the format FF-FF or 0xFF-0xFF as this is just a waste of space. For example most databases will represent their blobs as 0xFFFF when human readability is desired, text (hex, rather than base64 obviously) representation of things like hashes is always in the format 0xFFFF or just FFFF, etc. An example of this is the format of an MD5sum file such as this one.
It is standard for the number of characters to be twice the number of bytes but my snippet also pads the first or last byte with a 0 if this is not the case, for example "fff" can be padded to "0fff" or "ff0f" and then treated normally. (The endianness of the data specifies whether "fff" should be treated as 15,255 or 255,15 but you cannot tell this just from the string)
My snippet also already uses the same number of iterations in the for loop as the snippet you have just posted. It just creates a byte array half the length of the string and loops for each of those bytes incrementing by 1, multiplying by 2 to get the string offset rather than dividing by 2 to get the index offset and incrementing by 2. Essentially I am doing "for each byte in the destination array" and you are doing "for each pair of characters in the source string" . In days of old, this would have been a better way of doing it (* rather than /, ++ rather than += 2 etc) but I suspect that modern compilers and modern machines mean that the difference in performance is negligible, particularly on a managed environment. Regardless, I think that it is slightly more readable and any performance benefit that doesn't reduce readability is always a bonus.
As you have shown, you can pass a string in the format FF-FF or even 0xFF-0xFF into my method anyway simply by replacing the - or "0x" with String.Empty. The only problem with this is that F-FF should clearly be treated as 0FFF while FF-F should clearly be treated as FF0F, so any implied endianness is lost when the -s are removed. Obviously not a problem if it is FF-0F in the first place. Ideally, if you know in advance that the string is in the format FF-FF, your code that splits on '-' is better. In all other cases, it is not usable.
The point really is that there are many ways of doing this that are better than the code in the article.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
The argument range is limited by Int32.MaxValue and Int32.MinValue. "fae0b7abcd" will throw an OverflowException.
|
| Sign In·View Thread·PermaLink | 5.00/5 (2 votes) |
|
|
|
 |
|
|
I needed this so that I could easily convert Hex into a Byte Array. Once converted to a byte array I sent the byte packet out of a serial port to control my Pan Tilt Zoom camera pod. This class made that conversion very very simple to do.
|
| Sign In·View Thread·PermaLink | 1.00/5 (1 vote) |
|
|
|
 |
|
|
using System; using System.Collections.Generic; using System.Text;
namespace Utilities { public class MyHexConverter { /// <summary> /// Helper array to speedup conversion /// </summary> static string[] BATHS = { "00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0A", "0B", "0C", "0D", "0E", "0F", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "1A", "1B", "1C", "1D", "1E", "1F", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "2A", "2B", "2C", "2D", "2E", "2F", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "3A", "3B", "3C", "3D", "3E", "3F", "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "4A", "4B", "4C", "4D", "4E", "4F", "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "5A", "5B", "5C", "5D", "5E", "5F", "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "6A", "6B", "6C", "6D", "6E", "6F", "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "7A", "7B", "7C", "7D", "7E", "7F", "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "8A", "8B", "8C", "8D", "8E", "8F", "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "9A", "9B", "9C", "9D", "9E", "9F", "A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9", "AA", "AB", "AC", "AD", "AE", "AF", "B0", "B1", "B2", "B3", "B4", "B5", "B6", "B7", "B8", "B9", "BA", "BB", "BC", "BD", "BE", "BF", "C0", "C1", "C2", "C3", "C4", "C5", "C6", "C7", "C8", "C9", "CA", "CB", "CC", "CD", "CE", "CF", "D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7", "D8", "D9", "DA", "DB", "DC", "DD", "DE", "DF", "E0", "E1", "E2", "E3", "E4", "E5", "E6", "E7", "E8", "E9", "EA", "EB", "EC", "ED", "EE", "EF", "F0", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "FA", "FB", "FC", "FD", "FE", "FF" }; static byte[] HSTB = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0, 10, 11, 12, 13, 14, 15 }; /// <summary> /// Function converts byte array to it's hexadecimal implementation /// </summary> /// <param name="ArrayToConvert">Array to be converted</param> /// <param name="Delimiter">Delimiter to be inserted between bytes</param> /// <returns>String to represent given array</returns> public static string ByteArrayToHexString(byte[] ArrayToConvert, string Delimiter) { int LengthRequired = ArrayToConvert.Length << 1 + Delimiter.Length * ArrayToConvert.Length + 1; StringBuilder tempstr = new StringBuilder(LengthRequired, LengthRequired); foreach (byte CurrentElem in ArrayToConvert) { tempstr.Append(BATHS[CurrentElem]); tempstr.Append(Delimiter); } tempstr.Remove(tempstr.Length - 1, 1); return tempstr.ToString(); }
/// <summary> /// Function converts given hexadecimal string to it's binary representation /// </summary> /// <param name="StringToConvert">String to convert to byte array</param> /// <returns>Byte array representing given string</returns> public static byte[] PureHexStringToByteArray(string StringToConvert) { byte[] temparr = new byte[StringToConvert.Length / 2]; byte Char1, Char2; for (int i = 0; i < StringToConvert.Length; i = i + 2) { Char1 = (Byte)StringToConvert[i]; Char2 = (Byte)StringToConvert[i + 1]; temparr[i / 2] = (Byte)((HSTB[(Char1 - 48)] << 4) + HSTB[(Char2 - 48)]); } return temparr; } } }
|
| Sign In·View Thread·PermaLink | 3.00/5 (2 votes) |
|
|
|
 |
|
|
static string[] BATHS = { "00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0A", "0B", "0C", "0D", "0E", "0F", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "1A", "1B", "1C", "1D", "1E", "1F", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "2A", "2B", "2C", "2D", "2E", "2F", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "3A", "3B", "3C", "3D", "3E", "3F", "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "4A", "4B", "4C", "4D", "4E", "4F", "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "5A", "5B", "5C", "5D", "5E", "5F", "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "6A", "6B", "6C", "6D", "6E", "6F", "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "7A", "7B", "7C", "7D", "7E", "7F", "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "8A", "8B", "8C", "8D", "8E", "8F", "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "9A", "9B", "9C", "9D", "9E", "9F", "A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9", "AA", "AB", "AC", "AD", "AE", "AF", "B0", "B1", "B2", "B3", "B4", "B5", "B6", "B7", "B8", "B9", "BA", "BB", "BC", "BD", "BE", "BF", "C0", "C1", "C2", "C3", "C4", "C5", "C6", "C7", "C8", "C9", "CA", "CB", "CC", "CD", "CE", "CF", "D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7", "D8", "D9", "DA", "DB", "DC", "DD", "DE", "DF", "E0", "E1", "E2", "E3", "E4", "E5", "E6", "E7", "E8", "E9", "EA", "EB", "EC", "ED", "EE", "EF", "F0", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "FA", "FB", "FC", "FD", "FE", "FF" };
public static string ByteArrayToHexString(byte[] ArrayToConvert, char Delimiter) { char[] list = new char[ArrayToConvert.Length * 3];
for (int k = 0; k < ArrayToConvert.Length; ++k) { list[k * 3 + 0] = BATHS[ArrayToConvert[k]][0]; list[k * 3 + 1] = BATHS[ArrayToConvert[k]][1]; list[k * 3 + 2] = Delimiter; }
return new string(list); }
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
|
|
 |
|
|
is that your HexEncoding will support big endian hex numbers? for example, the header signature of JPG file is 0x04034b50 and HexEncoding will convert this as { 4,3,75,80 } - which is correct. But, any way to provide a functionality to convert bigendian hex. It would be great thing to have in there.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
http://msdn2.microsoft.com/en-us/library/system.runtime.remoting.metadata.w3cxsd2001.soaphexbinary.aspx[^]
From MSDN
using System; using System.Runtime.Remoting.Metadata.W3cXsd2001;
public class Demo { public static void Main(string[] args) { // Parse an XSD formatted string to create a SoapHexBinary object. string xsdHexBinary = "3f789ABC"; SoapHexBinary hexBinary = SoapHexBinary.Parse(xsdHexBinary);
// Print the value of the SoapHexBinary object in XSD format. Console.WriteLine("The SoapHexBinary object in XSD format is {0}.", hexBinary.ToString());
// Print the XSD type string of this particular SoapHexBinary object. Console.WriteLine( "The XSD type of the SoapHexBinary object is {0}.", hexBinary.GetXsdType());
// Print the value of the SoapHexBinary object. Console.Write("hexBinary.Value contains:"); for (int i = 0 ; i < hexBinary.Value.Length ; ++i) { Console.Write(" " + hexBinary.Value[i]); } Console.WriteLine();
// Print the XSD type string of the SoapHexBinary class. Console.WriteLine("The XSD type of the class SoapHexBinary is {0}.", SoapHexBinary.XsdType); } }
|
| Sign In·View Thread·PermaLink | 5.00/5 (2 votes) |
|
|
|
 |
|
|
This is exactly what I was looking for. I was looking for something that was built into .NET versus writing custom code. The HexEncoding class also worked great btw.
www
|
| Sign In·View Thread·PermaLink | 1.00/5 (1 vote) |
|
|
|
 |
|
|
Yep, SoapHexBinary handles all very smoothly. Have anybody made any perfomance test which method is faster?
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
Be wary of this if you're using it to convert user input. It discards all spaces, so if a user enters 1 44 a, they'll actually end up with 14 4a instead of 01 44 0a.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
General News Question Answer Joke Rant Admin
|