none
byte[] Array to Hex String

    Question

  • is there any method provide in .net for conversion like byteToHex(byte[])?

    Byte[] Bytes = {0xFF, 0xD0, 0xFF, 0xD1} to "FFD0FFD1" ?

    thnx
    Wednesday, June 28, 2006 3:40 AM

Answers

  • Note however, if

    Byte[] Bytes = {0xFF, 0xD0, 0xFF, 0xD1} to "FF-D0-FF-D1"

    is acceptable, you can use:

    BitConverter.ToString(Bytes);


     

    Wednesday, June 28, 2006 4:31 AM

All replies

  • None that I've found.  I use:

    StringBuilder sb = new StringBuilder(ba.Length * 2);
    foreach (byte b in
    ba)
    {
           sb.AppendFormat(
    "{0:x2}"
    , b)
    }
    return
    sb.ToString();

    Wednesday, June 28, 2006 4:26 AM
  • Note however, if

    Byte[] Bytes = {0xFF, 0xD0, 0xFF, 0xD1} to "FF-D0-FF-D1"

    is acceptable, you can use:

    BitConverter.ToString(Bytes);


     

    Wednesday, June 28, 2006 4:31 AM
  • thnx a lot, this work for me

    string hex = BitConverter.ToString(Bytes);
    hex = hex.Replace("-","");

    although not "one-step" solution, but great enough
    Wednesday, June 28, 2006 5:59 AM
  • Faster variant:

        public class JSMHexConverter
        {
            /// <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" };
           
            /// <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>
            static string ByteArrayToHexString(byte[] ArrayToConvert, string Delimiter)
            {
                int LengthRequired = (ArrayToConvert.Length + Delimiter.Length) * 2;
                StringBuilder tempstr = new StringBuilder(LengthRequired, LengthRequired);
                foreach(byte CurrentElem in ArrayToConvert)
                {
                    tempstr.Append(BATHS[CurrentElem]);
                    tempstr.Append(Delimiter);
                }

                return tempstr.ToString();
            }

    }
    Sunday, March 04, 2007 8:34 PM
  • Here's my function:

     

    public static string HexStr(byte[] p) {

    char[] c=new char[p.Length*2 + 2];

    byte b;

    c[0]='0'; c[1]='x';

    for(int y=0, x=2; y<p.Length; ++y, ++x) {

    b=((byte)(p[y ]>>4));

    c[x]=(char)(b>9 ? b+0x37 : b+0x30);

    b=((byte)(p[y ]&0xF));

    c[++x]=(char)(b>9 ? b+0x37 : b+0x30);

    }

    return new string(c);

    }

     
    it puts "0x" at the beginning of the string, but that's a simple matter to change.
     

    HexStr(new byte[]{0x00,0xDE,0xAD,0xBE,0xEF,0x99}) ==> "0x00DEADBEEF99"

     
    Sorry to cut you off up there, but when dealing with big arrays, every character - every processor cycle - counts.
    • Proposed as answer by R Shillington Saturday, May 31, 2008 11:13 AM
    Thursday, November 08, 2007 6:53 PM
  • If I caught anyone using anything but BitConverter.ToString and trying to roll their own solution, I would fire them on the spot.
    Tuesday, April 28, 2009 11:08 AM
  • If I caught anyone using anything but BitConverter.ToString and trying to roll their own solution, I would fire them on the spot.

    If I caught anyone necroing 18-month old threads to make macho threats, I'd fire them on the spot.

    Especially if the answer they gave was already posted in that thread almost three years before...

    :)

    Tuesday, April 28, 2009 11:37 AM
  • This is truly LOL material!
    Ole - Andre Johansen
    Tuesday, April 28, 2009 1:06 PM
  • If I would order an application with you, and the preocess takes 40 time longer, because your team has to use BitConverter instead of any other clean approach, I would never give you a job again.
    In my case we convert thousands of times a few thousand bytes, all that while the user is operating the PC. I made some time measurements:
    BitConverter + String.Replace("-", ""): 203407
    Fractals mapping approach: 6609
    PZahras approach: 4903

    I can not understand how you justify, to fire a good developer and deliver a solution which takes 40 times as long.

    In my opinion all 3 approaches are good, depending on your problem, the solution may totally differ. None of the solutions uses unsafe code, so I can not see how it would interfere with any clean code policies.

    Thank you all for your great solutions :-)
    Tuesday, May 05, 2009 12:25 AM
  •                        hi use this
       
                            string hexString = string.Empty;
    for (int i=0; i<bytes.Length; i++)
    {
    hexString += bytes[i].ToString("X2");
    }
    return hexString;
    Thursday, October 08, 2009 4:26 PM
  •                        hi use this
       
                            string hexString = string.Empty;
    for (int i=0; i<bytes.Length; i++)
    {
    hexString += bytes[i].ToString("X2");
    }
    return hexString;


    Well done sandeeprwt - I have used this in my code and it works brilliantly.  Simple, elegant and efficient - what is it that makes developers go for the most complex solutions when you can do something like this.  If you used the stringbuilder though that would be even better because the += has to create a new string each time. 

    StringBuilder sb = new StringBuilder();

    for (int i = 0; i < _data.Length; i++)
    {
        sb.Append(bites[i].ToString("X2"));
    }

    return sb.ToString();

    As for gurhalls comments - I'd fire him on the spot for NOT thinking up a solution like this because it proves he hasnt got the necessary skills to be a decent developer.  I am assuming he is some form of a manager - speaks volumes doesn't it!

    Wednesday, October 28, 2009 6:40 AM
  • Is there an equally simple solution to  go from Hexstring to Byte[] or even to int?

    By the way, I had a manager like the above mentioned. He went through several "unqualified" engineers and myself before he "left" the company because he could not handle the stress (was driven out).
    Thursday, November 12, 2009 5:55 PM
  • There's an easy one to go from a hex string to an int, but not from hex string to array of bytes:

    using System;
    using System.Diagnostics;
    using System.Globalization;
    
    namespace ConsoleApplication1
    {
        static class Program
        {
            static void Main()
            {
                // Convert from hex string to int using int.Parse():
                string hexInt = "ABCD1234";
                int number = int.Parse(hexInt, NumberStyles.HexNumber);
                Console.WriteLine(number.ToString("X"));
    
                // Convert from hex string to byte array using a custom method:
                string hexString = "0102030405060708090a0b0c0d0e0fAAABACADAEAF";
                byte[] bytes = HexStringToBytes(hexString);
                string converted = BitConverter.ToString(bytes).Replace("-", null);
                Console.WriteLine(converted);
                Debug.Assert(string.Compare(converted, hexString, true) == 0);
            }
    
            static byte[] HexStringToBytes(string hexString)
            {
                if (hexString == null)
                {
                    throw new ArgumentNullException("hexString");
                }
    
                if ((hexString.Length & 1) != 0)
                {
                    throw new ArgumentOutOfRangeException("hexString", hexString, "hexString must contain an even number of characters.");
                }
    
                byte[] result = new byte[hexString.Length/2];
    
                for (int i = 0; i < hexString.Length; i += 2)
                {
                    result[i/2] = byte.Parse(hexString.Substring(i, 2), NumberStyles.HexNumber);
                }
    
                return result;
            }
        }
    }
    
    Friday, November 13, 2009 10:01 AM
  • And even better - set the capacity of the StringBuilder:

    StringBuilder sb = new StringBuilder(_data.Length * 2);
    Monday, December 28, 2009 5:58 AM
  • Actually; the real problem is MS should be providing a proper .net component to handle low level byte mapping. I know they want us "amateurs" to use more abstract components (eg Encoder, StreamWriter, etc), but sometimes all I want to do is a "hello world" app without needing to write a gigantic library to do something as basic as converting byte arrays.
    Sunday, January 03, 2010 7:32 PM
  • What do you call "low level byte mapping"?
    Creating a string containing the hexadecimal representation of each element of a byte array is not what I would call "low level" or "byte mapping".
    Monday, January 04, 2010 2:17 AM
  • Hehe.. this thread goes on for almost 4 years...

    Well, here's my one-line approach..


    string.Concat(byteArray.Select(b => string.Format("{0:X2} ", b)));

    cheers..
    Tuesday, February 23, 2010 5:15 PM
  • Awesome!
    Friday, March 12, 2010 9:27 PM
  • If you're looking for pure speed try:

            public static string HexStr(byte[] data)
            {
                char[] lookup = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
                int i = 0, p = 2, l = data.Length;
                char[] c = new char[l * 2 + 2];
                byte d; c[0] = '0'; c[1] = 'x';
                while (i < l)
                {
                    d = data[i++];
                    c[p++] = lookup[d / 0x10];
                    c[p++] = lookup[d % 0x10];
                }
                return new string(c, 0, c.Length);
            }

    Which works out about 30% faster than PZahras (not that you'd notice with small amounts of data).

    The BitConverter method itself is pretty quick, it's just having to do the replace which slows it down, so if you can live with the dashes then it's perfectly good.



    • Proposed as answer by PZahra Monday, April 19, 2010 5:26 PM
    Monday, March 15, 2010 5:11 PM
  • Oh, well done, Fraser. Fast is good. Of course, reading from text is always going to be slower...

     

    public static byte[] HexByte(string str, int offset, int step, int tail) {
    	byte[] b = new byte[(str.Length - offset - tail + step) / (2 + step)];
    	byte c1, c2;
    	int l = str.Length - tail;
    	int s = step + 1;
    	for(int y = 0, x = offset; x < l; ++y, x += s) {
    		c1 = (byte)str[x];
    		if(c1 > 0x60) c1 -= 0x57;
    		else if(c1 > 0x40) c1 -= 0x37;
    		else c1 -= 0x30;
    		c2 = (byte)str[++x];
    		if(c2 > 0x60) c2 -= 0x57;
    		else if(c2 > 0x40) c2 -= 0x37;
    		else c2 -= 0x30;
    		b[y] = (byte)((c1 << 4) + c2);
    	}
    	return b;
    }
    
    
    ... Especially if you're going to make it case insensitive. I added the offset so as to not waste time with substring when you want to ignore the 0x, &H, $, #, Hex(...) or whatever other symbol is used. Also, step to ignore spacing and tail to cut off quotes and stuff at the end. I didn't fully test this, so enjoy.

     


    • Proposed as answer by Lentucky Tuesday, August 03, 2010 1:49 AM
    • Edited by PZahra Wednesday, June 08, 2011 4:27 PM
    Thursday, April 15, 2010 3:46 PM
  • actually it has a little error.

     

    if you have a string like this: "12 34 56 78"  your "step" will be one.

    but when you calculate the byte array size you don't take this into account. So, you will have a 11/2 = 5 size array.

    so, we need to put like this:

     

    byte[] b = new byte[(str.Length - offset - tail) / (2 + step)];

     

    but, it is not enough. If the string is exactly like i said before the result will be 3 because using the "+ step" take into account a space in the end of the last element (string). So the solution for this can take several verifications and can be done in several ways. Maybe the easy way is to make mandatory an odd string, or add a space at the end (maybe showing a Alert Box to the user asking if it is the right thing to do)

    any doubts, just ask.

     

    sorry for some English errors, not my natural language.

    Monday, April 19, 2010 6:05 PM
  • You're right. I added Step at the last second. This should do it:

    byte[] b = new byte[(str.Length - offset - tail + step) / (2 + step)];

    • Proposed as answer by Lentucky Tuesday, August 03, 2010 1:49 AM
    Tuesday, April 20, 2010 2:15 PM
  • Hey guys, here is another variant using bitwise operations (i love them :D) it's based on matthews code.

     

            public static string HexStr(byte[] data)
            {
                char[] lookup = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };

                StringBuilder sb = new StringBuilder(data.Length * 2);

                for(int buc = 0; buc < data.Length; buc++)

                {
                    sb.Append(lookup[(data[buc] >> 4) & 0x0F]);
                    sb.Append(lookup[data[buc] & 0x0F]);
                }

                return sb.ToString();
            }

    Tuesday, August 03, 2010 1:33 AM
  • 1. Lookup tables should always be static. When you declare them inside a method, they get allocated on the heap every time the method is called.

    2. Temporary arrays should be allocated on the stack for the same reason. Just be careful of the 1MB stack limit. That's why this example uses sbyte instead of char.

    You may not see a significant speed increase, but the only object that get allocated by the runtime is the string itself.

     

    private static readonly sbyte[] _lookup = new sbyte[] { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 };
    public static unsafe string ToHex(this byte[] arr)
    {
     int len = arr.Length;
     int i = 0;
    
     sbyte* chars = stackalloc sbyte[len * 2];
     fixed (byte* pSrc = arr)
     {
     byte* pIn = pSrc;
     sbyte* pOut = chars;
     while (i++ < len)
     {
      *pOut++ = _lookup[*pIn >> 4];
      *pOut++ = _lookup[*pIn++ & 0xF];
     }
     }
     return new String(chars, 0, len * 2);
    }
    Thursday, November 18, 2010 5:56 PM
  • If I caught anyone using anything but BitConverter.ToString and trying to roll their own solution, I would fire them on the spot.

    If I caught anyone necroing 18-month old threads to make macho threats, I'd fire them on the spot.

    Especially if the answer they gave was already posted in that thread almost three years before...

    :)


    LOL, then just fire me Mr. Donald Trump wanna be:

    here is a Linq solution, probably more elegant than the BitConverter:

    public static class HelperTools
    
    {
    
    public static string ToHexString(this IEnumerable<byte> bytes)
    { 
     
    return new string(bytes.SelectMany(x => x.ToString("X2").ToCharArray()).ToArray()); 
     
    
    }
    
    } 
    
    //and you use it like this:
    
    Byte[] Bytes = {0xFF, 0xD0, 0xFF, 0xD1} ;
    
    string hexstr = Bytes.ToHexString();
    
    
    

    Now Mr. trump is waiting in the board room! Who's gonna get fired?

     

    • Edited by dmihailescu Friday, February 04, 2011 4:38 PM code block
    Friday, February 04, 2011 4:32 PM
  • Your solution is another interesting one! I like the use of an extension method.

    The linq itself I wouldn't describe as elegant personally. But I guess that's a matter of opinion!

    Friday, February 04, 2011 4:56 PM
  • Hello all,

    Sorry for refreshing a thread that is so old but I basically want to do similar thing that has been asked here only I want the byte[] array to be parsed as a .reg file. Moreover I want to do it in NETCF on PocketPC.
    What I do is to take a value from registry:

     

    RegistryKey RgKey = Registry.LocalMachine.OpenSubKey("\Time")
    string RgName = "TimeZoneInformation"
    
    string ValueType = Convert.ToString(RgKey.GetValueKind(RgName));
    obj Value = RgKey.GetValue(RgName);
    

     

    (I know the ValueType and Value variables don't make any sense assigned this way, but what I need to get is a unicode text file (a .reg file) with something like this:

    [HKEY_LOCAL_MACHINE\Time]
    "TimeZoneInformation"=hex:c4,ff,ff,ff,45,00,75,00,72,00,6f,00,70,00,61,00,20,\
    00,5a,01,72,00,6f,00,64,00,6b,00,6f,00,77,00,61,00,20,00,28,00,63,00,7a,00,61,\
    00,73,00,20,00,73,00,74,00,61,00,6e,00,64,00,2e,00,29,00,00,00,00,00,00,00,00,\
    00,0a,00,00,00,05,00,03,00,00,00,00,00,00,00,00,00,00,00,45,00,75,00,72,00,6f,\
    00,70,00,61,00,20,00,5a,01,72,00,6f,00,64,00,6b,00,6f,00,77,00,61,00,20,00,28,\
    00,63,00,7a,00,61,00,73,00,20,00,6c,00,65,00,74,00,6e,00,69,00,29,00,00,00,00,\
    00,00,00,00,00,00,00,03,00,00,00,05,00,02,00,00,00,00,00,00,00,c4,ff,ff,ff

     

    I know how to parse the key name (it's the easiest task), and I even have the idea to make a condition for showing the type of the data properly. But I have no idea how  to parse the "Value" to have the notation like in the above example...


    Do you think you can help me?

     

    Friday, May 20, 2011 12:56 AM
  • @dmihailescu

    Speed check pls., consistent with Dennis Kuhn's tests.

     

    @Skrobel

    Assuming you're using GetPrivateProfileString to parse the line breaks properly, my HexByte function should work for you. Just set Offset to 4, Step 1, Tail 0.

    Wednesday, June 08, 2011 4:24 PM
  • Honestly I parsed the line breaks with a bit "manual" method. After a few nights of thinking (perhaps I'm just not smart enough to do it sooner) I realized that it's a matter of formatting string and not of converting it. And here's what I did:

     RegistryKey RgKey = Registry.LocalMachine.OpenSubKey("\\Time");
     string RgName = "Time";
     string Txt = null;
     string Tmp = null;
      byte[] data = (byte[])RgKey.GetValue(RgName);
      for (int i = 0; i < data.Length; i++)
      {
      if (i % 24 == 0)
       Tmp = Tmp + "\\\n";
      Tmp = Tmp + String.Format("{0:X2}", data[i]);
      if (i < data.Length - 1)
       Tmp = Tmp + ",";
      }
      Txt = RgName + "=hex:" + Tmp;
      break;

    It was easier than I thought. I hope this will come in handy to someone else.


    Wednesday, June 08, 2011 9:56 PM
  • Here's what I use:

    BitConverter.ToString(encodedTextBytes).Replace("-", string.Empty);

    Thursday, May 10, 2012 4:21 PM
  • There's no need to give an answer which has already been given in a several-years-old thread.
    Monday, May 14, 2012 1:06 AM
  • If there is no need to give an answer, then why not just remove the thread.  This is the thinking that results in hours of wasted time reading threads that have no answers.  I am reading this thread 7 years later, and I greatly appreciate all the solutions given.  Threads like this are meant to be read by the general public years after the initial discussion.  Otherwise we will just keep asking the same question over and over.
    Wednesday, May 23, 2012 1:15 AM
  • Thanks to timster at home.  I decided to use his solution (using StringBuilder) in my project.  To all those reading this thread (years later), the information given is still relevant and useful.  Remember, however, that the .net language is still evolving so you may want to check more recent solutions.  BTW I prefer StringBuilder because I am developing a serial port program and I don't want to keep creating new strings every time new data comes in.  If you don't understand this, check into the idea of C++ strings being immutable.

    Wednesday, May 23, 2012 1:37 AM
  • If there is no need to give an answer, then why not just remove the thread.

    Calm down. Read again. "an answer which has already been given"

    If you're going to answer an old thread, at least give a new answer.

    Wednesday, May 23, 2012 8:33 AM