Either: public static string ByteArrayToString(byte ba) { StringBuilder hex = new StringBuilder(ba. Length * 2); foreach (byte be in ba) hex. AppendFormat("{0:x2}", b); return hex.ToString(); } or: public static string ByteArrayToString(byte ba) { string hex = BitConverter.
ToString(ba); return hex. Replace("-",""); } There are even more variants of doing it, for example here. The reverse conversion would go like this: public static byte StringToByteArray(String hex) { int NumberChars = hex.
Length; byte bytes = new byteNumberChars / 2; for (int I = 0; I.
Missing a semicolon on hex. AppendFormat("{0:x2}", b) line – devfuel Dec 23 '08 at 0:37 2 You're using SubString. Doesn't this loop allocate a horrible amount of string objects?
– Wim Coenen Mar 6 '09 at 16:36 3 Honestly - until it tears down performance dramatically, I would tend to ignore this and trust the Runtime and the GC to take care of it. – Tomalak Mar 6 '09 at 17:11 1 Your StringToByteArray() fails if you have an odd number of hex characters. This is easily fixed by padding odd strings with a "0" at the front.
– Carlos Rendon Nov 23 '09 at 17:21 15 Because a byte is two nibbles, any hex string that validly represents a byte array must have an even character count. A 0 should not be added anywhere - to add one would be making an assumption about invalid data that is potentially dangerous. If anything, the StringToByteArray method should throw a FormatException if the hex string contains an odd number of characters.
– David Boike Mar 9 '10 at 19:01.
There's a class called SoapHexBinary that does exactly what you want. Using System.Runtime.Remoting.Metadata. W3cXsd2001; public byte GetStringToBytes(string value) { SoapHexBinary shb = SoapHexBinary.
Parse(value); return shb. Value; } public string GetBytesToString(byte value) { SoapHexBinary shb = new SoapHexBinary(value); return shb.ToString(); }.
5 SoapHexBinary is available from . NET 1.0 and is in mscorlib. Despite it's funny namespace, it does exactly what the question asked.
– Sly Jun 28 '11 at 6:48 Great find! Note that you will need to pad odd strings with a leading 0 for GetStringToBytes, like the other solution. – Carter Oct 31 '11 at 17:10.
If you want more flexibility than BitConverter, but don't want those clonky 90s-style explicit loops, then you can do: String. Join(String. Empty, Array.
ConvertAll(bytes, x => x. ToString("X2"))); Or, if you're using . NET 4.0: String.
Concat(Array. ConvertAll(bytes, x => x. ToString("X2"))); (The latter from a comment on the original post).
17 Even shorter: String. Concat(Array. ConvertAll(bytes, x => x.
ToString("X2")) – Nestor Nov 25 '09 at 15:04 Just a note that maxc's nice technique does need .net 4.0 – Will Dean Nov 25 '09 at 22:05 1 Even shorter: String. Concat(bytes. Select(b => b.
ToString("X2"))) . NET4 – Allon Guralnek Jun 16 '11 at 6:39 4 Only answers half the question. – Sly Jun 28 '11 at 6:50.
I just encountered the very same problem today and I came across this code: private static string ByteArrayToHex(byte barray) { char c = new charbarray. Length * 2; byte b; for (int I = 0; I > 4)); ci * 2 = (char)(b > 9? Be + 0x37 : be + 0x30); be = ((byte)(barrayi & 0xF)); ci * 2 + 1 = (char)(b > 9?
Be + 0x37 : be + 0x30); } return new string(c); } Source: social.msdn.microsoft.com/Forums/en-US/c... (see the post by PZahra) I modified the code a little to remove the 0x prefix I did some performance testing to the code and it was almost 8 times faster than using BitConverter.ToString() (the fastest according to patridge's post).
Not to mention that this uses the least memory. No intermediate strings created whatsoever. – Chochos Oct 16 '09 at 17:36 Only answers half the question.
– Sly Jun 28 '11 at 6:50.
You can use BitConverter. ToString Method: byte bytes = {0, 1, 2, 4, 8, 16, 32, 64, 128, 255 } Console. WriteLine( BitConverter.
ToString( bytes ) ); Output: 00-01-02-04-08-10-20-40-80-FF More Info: http://msdn.microsoft.com/en-us/library/3a733s97.aspx.
1 Only answers half the question. – Sly Jun 28 '11 at 6:49.
Performance Analysis I ran each of the various conversion methods through some crude Stopwatch performance testing, a run with a random sentence (n=98, 1000 iterations) and a run with a Project Gutenburg text (n=1,189,578, 150 iterations). Here are the results, roughly from fastest to slowest. All measurements are in ticks (10,000 ticks = 1 ms) and all relative notes are compared to the slowest StringBuilder implementation.
For the code used, see below or the BitBucket repo I threw together. Byte Manipulation Text: 115,811 (11.4 times faster) Sentence: 7.9 (10.8 times faster) BitConverter Text: 208,440 (6.3 times faster) Sentence: 19.0 (4.5 times faster) Array. ConvertAll (using string.
Concat, requires . NET 4.0) Text: 1,195,253 (1.1 times faster) Sentence: 65.3 (1.3 times faster) Array. ConvertAll (using string.
Join) Text: 1,202,390 (1.1 times faster) Sentence: 43.2 (2.0 times faster) {StringBuilder}. AppendFormat Text: 1,322,386 Sentence: 85 Byte manipulation, while harder to read, is definitely the fastest approach. BitConverter is second, even with the .
Replace("-", "") to match its output with the rest. The two Array. ConvertAll variants fight with each other for third place.
Testing Code Feel free to play with the testing code I used. A version is included here but feel free to clone the BitBucket repo. If you want to add a new method to test, add the new static method (Func) and add it to the methodsToCheck array.
Static void Main(string args) { byte testSubject = System.Text.ASCIIEncoding.ASCII. GetBytes("put any sample string you want to test here instead of a file"); Func methodsToCheck = new Func { ByteArrayToHexStringViaStringJoinArrayConvertAll, ByteArrayToHexStringViaStringConcatArrayConvertAll, ByteArrayToHexStringViaBitConverter, ByteArrayToHexStringViaStringBuilder, ByteArrayToHexViaByteManipulation }; string typicalAnswer = methodsToCheck0(testSubject); int iterations = 15; foreach (Func method in methodsToCheck) { string methodDescription = method.Method. Name; double averageRunTicks = GetAverageRun(method, testSubject, typicalAnswer, iterations); Console.
WriteLine("{0}: {1:0.0} average ticks (over {2} runs)", methodDescription, averageRunTicks, iterations); } Console.Read(); } static string ByteArrayToHexStringViaStringJoinArrayConvertAll(byte bytes) { return string. Join(string. Empty, Array.
ConvertAll(bytes, be => b. ToString("X2"))); } static string ByteArrayToHexStringViaStringConcatArrayConvertAll(byte bytes) { return string. Concat(Array.
ConvertAll(bytes, be => b. ToString("X2"))); } static string ByteArrayToHexStringViaBitConverter(byte bytes) { string hex = BitConverter. ToString(bytes); return hex.
Replace("-", ""); } static string ByteArrayToHexStringViaStringBuilder(byte bytes) { StringBuilder hex = new StringBuilder(bytes. Length * 2); foreach (byte be in bytes) hex. AppendFormat("{0:X2}", b); return hex.ToString(); } static string ByteArrayToHexViaByteManipulation(byte bytes) { char c = new charbytes.
Length * 2; byte b; for (int I = 0; I > 4)); ci * 2 = (char)(b > 9? Be + 0x37 : be + 0x30); be = ((byte)(bytesi & 0xF)); ci * 2 + 1 = (char)(b > 9? Be + 0x37 : be + 0x30); } return new string(c); } static double GetAverageRun(Func operation, byte victim, string expectedOutput, int iterations) { string testResult = operation(victim); // also primes anything that may be a one-time cost Debug.
Assert(expectedOutput == testResult); List elapsedTicksCollection = new List(); Stopwatch timer; for (int I = 1; I Quite fast. Update (2011-10-05) Added string. Concat Array.
ConvertAll variant for completeness (requires . NET 4.0). On par with string.
Join version.
6 my eyes.............! – Pure. Krome May 21 '09 at 11:56 Would you care to test the code from Waleed's answer? It seems to be very fast.Stackoverflow.com/questions/311165/… – Cristi Diaconescu Dec 24 '09 at 21:16 1 Despite making the code available for you to do the very thing you requested on your own, I updated the testing code to include Waleed answer.
All grumpiness aside, it is much faster. – patridge Jan 13 '10 at 16:29 I got a different result when I used "ByteArrayToHexStringViaBitConverter" and "ByteArrayToHexStringViaStringBuilder". The latter one turned out to be "right".
Is there any reason why the result from the two functions should be different? – iJK Apr 20 '10 at 22:11 If it is still happening, the best I can guess at this point is some sort of system culture variation that is affecting the results. – patridge Oct 4 '11 at 21:36.
This is a great post. I like Waleed's solution. I haven't run it through patridge's test but it seems to be quite fast.
I also needed the reverse process, converting a hex string to a byte array, so I wrote it as a reversal of Waleed's solution. Not sure if it's any faster than Tomalak's original solution. Again, I did not run the reverse process through patridge's test either.
Private byte HexStringToByteArray(string hexString) { int hexStringLength = hexString. Length; byte be = new bytehexStringLength / 2; for (int I = 0; I 0x40? HexStringi - 0x37 : hexStringi - 0x30) 0x40?
HexStringi + 1 - 0x37 : hexStringi + 1 - 0x30; bi / 2 = Convert. ToByte(topChar + bottomChar); } return b; }.
This code assumes the hex string uses upper case alpha chars, and blows up if the hex string uses lower case alpha. Might want to do a "uppercase" conversion on the input string to be safe. – Marc Novakowski Jan 26 '10 at 19:17 That's an astute observation Marc.
The code was written to reverse Waleed's solution. The ToUpper call would slow down the algorithm some, but would allow it to handle lower case alpha chars. – Chris F Jan 26 '10 at 20:27 Convert.
ToByte(topChar + bottomChar) can be written as (byte)(topChar + bottomChar) – Amir Rezaei Feb 12 '11 at 21:17.
This problem could also be solved using a look-up table, this would require a small amount of static memory for both encoder and decoder, this method will however be fast: Encoder table 512B or 1024B (twice the size if both upper and lower case is needed) Decoder table 256B or 64KiB (either a single char look-up or dual char look-up) My solution uses 1024B for the encoding table, and 256B for decoding. Decoding private static readonly byte LookupTable = new byte { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; private static byte Lookup(char c) { var be = LookupTablec; if (b == 255) throw new IOException("Expected a hex character, got " + c); return b; } public static byte ToByte(char chars, int offset) { return (byte)(Lookup(charsoffset) 256). Methods for de/encoding streams or arrays should be implemented, this is just a proof of concept.
And to steal Tomalak's thunder... EXTENSION METHODS :) disclaimer: completely untested code, btw .. just thought i'd add a quick post public static ByteExtensions { public static string ToHexString(this byte value) { StringBuilder hex = new StringBuilder(ba. Length * 2); foreach (byte be in ba) { hex. AppendFormat("{0:x2}", b) } return hex.ToString() } } etc.. use either of his three solutions (with the last one being an extension method on a string).
From Microsoft's developers, a nice, simple conversion: public static string ByteArrayToString(byte ba) { // concat the bytes into one long string return ba. Aggregate(new StringBuilder(32), (sb, b) => sb. Append(b.
ToString("X2")) ).ToString(); } While the above is clean an compact, performance junkies will scream about it using enumerators. You can get peak performance with an improved version of Tomolak's original answer: public static string ByteArrayToString(byte ba) { StringBuilder hex = new StringBuilder(ba. Length * 2); for(int i=0; I Length; i++) // Don't just take my word for it... performance test each routine and inspect it's IL code for yourself.
And for inserting into an SQL string (if you're not using command parameters): public static String ByteArrayToSQLHexString(byte Source) { return = "0x" + BitConverter. ToString(Source). Replace("-", ""); }.
If you want to get the "4x speed increase" reported by wcoenen, then if it's not obvious: replace "hex. Substring(i, 2)" with "hexi+hexi+1" you could also take it a step further and get rid of the i+=2 by using i++ in both places.
In terms of speed, this seems to be better than anything here: public static string ToHexString(byte data) { byte b; int i, j, k; int l = data. Length; char r = new charl * 2; for (i = 0, j = 0; I > 4; rj++ = (char)(k > 9? K + 0x37 : k + 0x30); k = be & 15; rj++ = (char)(k > 9?
K + 0x37 : k + 0x30); } return new string(r); }.
Why make it complex. This is simple in visual studio.net 2008: C#: string hex = BitConverter. ToString(YourByteArray).
Replace("-", ""); VB: Dim hex As String = BitConverter. ToString(YourByteArray). Replace("-", "").
If performance matters, here's an optimized solution: static readonly char _hexDigits = "0123456789abcdef".ToCharArray(); public static string ToHexString(this byte bytes) { char digits = new charbytes. Length * 2; for (int I = 0; I DivRem(bytesi, 16, out d2); digits2 * I = _hexDigitsd1; digits2 * I + 1 = _hexDigitsd2; } return new string(digits); } It's about 2.5 times faster that BitConverter. ToString, and about 7 times faster that BitConverter.
ToString + removal of the '-' chars.
I did not get the code you suggested to work, Olipro. Hexi + hexi+1 apparently returned an int. I did, however have some success by taking some hints from Waleeds code and hammering this together.It's ugly as hell but it seems to work and performs at 1/3 of the time compared to the others according to my tests (using patridges testing mechanism).
Depending on input size. Switching around the? :s to separate out 0-9 first would probably yield a slightly faster result since there are more numbers than letters.
Public static byte StringToByteArray2(string hex) { byte bytes = new bytehex. Length/2; int bl = bytes. Length; for (int I = 0; I 'F'?
Hex2 * I - 0x57 : hex2 * I > '9'? Hex2 * I - 0x37 : hex2 * I - 0x30) 'F'? Hex2 * I + 1 - 0x57 : hex2 * I + 1 > '9'?
Hex2 * I + 1 - 0x37 : hex2 * I + 1 - 0x30); } return bytes; }.
For performance I would go with drphrozens solution. A tiny optimization for the decoder could be to use a table for either char to get rid of the "If some kind of check is made either on input or output data (could be CRC, checksum or whatever) the if (b == 255)... could be skipped and thereby also the method calls altogether. Using offset++ and offset instead of offset and offset + 1 might give some theoretical benefit but I suspect the compiler handles this better than me.
Private static readonly byte LookupTableLow = new byte { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; private static readonly byte LookupTable 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; private static byte LookupLow(char c) { var be = LookupTableLowc; if (b == 255) throw new IOException("Expected a hex character, got " + c); return b; } private static byte Lookupgh(char c) { var be = LookupTable if (b == 255) throw new IOException("Expected a hex character, got " + c); return b; } public static byte ToByte(char chars, int offset) { return (byte)(Lookupgh(charsoffset++) | LookupLow(charsoffset)); } This is just off the top of my head and has not been tested or benchmarked.
Yet another variation for diversity: public static byte FromHexString(string src) { if (String. IsNullOrEmpty(src)) return null; int index = src. Length; int sz = index / 2; if (sz = 0) { char lo = src--index; char hi = src--index; rcsz = (byte)( ( (hi >= '0' && hi = 'a' && hi = 'A' && hi = '0' && lo = 'a' && lo = 'A' && lo Lo - 'A' + 10 : 0 ) ); } return rc; }.
I suspect the speed of this will knock the socks off most of the other tests... Public Function BufToHex(ByVal buf() As Byte) As String Dim sB As New System.Text. StringBuilder For I As Integer = 0 To buf. Length - 1 sB.
Append(buf(i). ToString("x2")) Next I Return sB. ToString End Function.
You create a new string object for every byte in the buffer, and you don't pre-size the string builder (which can lead to the buffer being resized multiple times on large arrays). – Brian Reichle Dec 2 '11 at 13:50.
I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.