|
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!
|
|
|
|
|
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.
|
|
|
|
|
all version are good.
THE END
|
|
|
|
|
The argument range is limited by Int32.MaxValue and Int32.MinValue. "fae0b7abcd" will throw an OverflowException.
|
|
|
|
|
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.
|
|
|
|
|
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;
}
}
}
|
|
|
|
|
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);
}
|
|
|
|
|
Yes, it seem so. Just custom-length delimiter is not supported.
|
|
|
|
|
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.
|
|
|
|
|
http://msdn2.microsoft.com/en-us/library/system.runtime.remoting.metadata.w3cxsd2001.soaphexbinary.aspx[^]
From MSDN
<br />
using System;<br />
using System.Runtime.Remoting.Metadata.W3cXsd2001;<br />
<br />
public class Demo<br />
{<br />
public static void Main(string[] args)<br />
{<br />
string xsdHexBinary = "3f789ABC";<br />
SoapHexBinary hexBinary = SoapHexBinary.Parse(xsdHexBinary);<br />
<br />
Console.WriteLine("The SoapHexBinary object in XSD format is {0}.",<br />
hexBinary.ToString());<br />
<br />
Console.WriteLine(<br />
"The XSD type of the SoapHexBinary object is {0}.",<br />
hexBinary.GetXsdType());<br />
<br />
Console.Write("hexBinary.Value contains:");<br />
for (int i = 0 ; i < hexBinary.Value.Length ; ++i)<br />
{<br />
Console.Write(" " + hexBinary.Value[i]);<br />
}<br />
Console.WriteLine();<br />
<br />
Console.WriteLine("The XSD type of the class SoapHexBinary is {0}.",<br />
SoapHexBinary.XsdType);<br />
}<br />
}
|
|
|
|
|
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
|
|
|
|
|
Yep, SoapHexBinary handles all very smoothly. Have anybody made any perfomance test which method is faster?
|
|
|
|
|
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.
|
|
|
|
|
Didnt have to to do this pattern again - thanks!
Tim.Smith@Venturality.com
|
|
|
|
|
Thanks a lot you did lots of work for me..
very simple and very usuful..
thanks again..
sinan
|
|
|
|
|
I am trying to convert '3e5a43e6'H to string and I get the converted value as ">ZCae" but the right value is ">ZC." . For some reason '.' is not properly converted. Here is another example '0a001351'H where in there are 3 '.' and its equivalent is "...Q" but the above conversion routine converts it to something else. Help appreciated.
|
|
|
|
|
<code>
public string IntToHex(int number)
{
return String.Format("{0:x}", number);
}
</code>
|
|
|
|
|
The hex string is limited to the MaxValue of int
|
|
|
|
|
hi there iam astudent in IT department i wanna ask you afavor i ha ve an assinment about mulithreaded applications i want you send me ideas about this problem.and i have also an assinment in image processing (spatial filter ,smooth filter,segmentation of an image)please reply me as fast as you can...
thanx alot.
|
|
|
|
|
Hi,
public static bool IsHexDigit(Char c)
{
int numChar;
int numA = Convert.ToInt32('A');
int num1 = Convert.ToInt32('0');
c = Char.ToUpper(c);
numChar = Convert.ToInt32(c);
if (numChar >= numA && numChar < (numA + 6))
return true;
if (numChar >= num1 && numChar < (num1 + 10))
return true;
return false;
}
Can be replaced with:
public static bool System.Uri.IsHexDigit(Char character);
There are some useful static methods in the Uri class for dealing with hex strings.
Shaun Brown, MCAD, MCSD
|
|
|
|
|
Thanks to everyone who have posted performance tips, and all the positive feedback.
I have not updated the article with the speed-ups suggested, because the code people have commented with is quite clear if someone needs it.
I do often use the StringBuilder class, and it should be used if you are converting a large amount of data, but left it out of the example for clarity.
|
|
|
|
|
This may not be the 'best' way to do it, but I was able to drop the class in my code and using your example I was converting numbers in just a few minutes. Hey... no thinking required , just what I needed.
Thanks,
Joe
More stuff at www.smileymicros.com
|
|
|
|
|
Great work neilck! I really appreciate you putting up your work for us.
Thanks again!
|
|
|
|
|
If someone really looks at performance, this is the fastest method I found on the net
public static string ToHexString(byte[] bytes)
{
char[] hexDigits = {
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
};
char[] chars = new char[bytes.Length * 2];
for (int i = 0; i < bytes.Length; i++)
{
int b = bytes[i];
chars[i * 2] = hexDigits[b >> 4];
chars[i * 2 + 1] = hexDigits[b & 0xF];
}
return new string(chars);
}
|
|
|
|
|
Stotti, you have definitely found the most efficient method. Using a fixed char array is much faster than StringBuilder!
|
|
|
|
|