Reputation: 279
I copied and pasted this binary data out of sql server, which I am unable to query at this time.
0xBAC893CAB8B7FE03C927417A2A3F6A60BD30FF35E250011CB25507EBFCD5223B
How do I convert it back to a byte array in c#?
Upvotes: 10
Views: 21786
Reputation: 41
maybe this one is cute!
string source = "Hello World!";
using (SHA256 sha256Hash = SHA256.Create())
{
//From String to byte array
byte[] sourceBytes = Encoding.UTF8.GetBytes(source);
byte[] hashBytes = sha256Hash.ComputeHash(sourceBytes);
string hash = BitConverter.ToString(hashBytes).Replace("-", String.Empty);
Console.WriteLine("The SHA256 hash of " + source + " is: " + hash);
}
Upvotes: 0
Reputation: 4976
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();
}
Upvotes: 0
Reputation: 2194
Slow yet fun 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
Upvotes: 1
Reputation: 53
Actually, there's an easier way to convert two characters at a time to a byte:
/// <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();
}
Upvotes: 1
Reputation: 6983
Consider leveraging a Framework class that already exposes the ability to perform hex conversion, XmlReader for example:
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;
}
usage:
string input = "0xBAC893CAB8B7FE03C927417A2A3F6A60BD30FF35E250011CB255";
byte[] bytes = input.HexToBytes(2, input.Length);
Upvotes: 6
Reputation: 1500095
Something like this:
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 slightly more efficient - no substrings required...)
It's possible that ParseNybble
could be more efficient. For example, a switch/case 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 lookup 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 haven't benchmarked any of these, and I've no idea which would be the fastest. The current solution is probably the simplest though.
Upvotes: 22
Reputation: 2737
Something like this:
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;
}
Upvotes: 3
Reputation: 7010
Simple:
string hexnum = "0000000F"; // Represents 15
int value = int.Parse(hexnum, System.Globalization.NumberStyles.HexNumber);
All you have to remember to do is for an int to divide the hex number up into groups of 8 hex digits (hex are 4 bits each, and CLR int type is 32 bits, hence 8 digits per int). There's also a byte.Parse() that works the same, but pass in two hex digits at a time.
Upvotes: 4
Reputation: 10038
You will need to modify this a little bit (for example, skip over the first two characters), but it does handle spaces in the string:
/// <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, a-f, A-F].</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;
}
Upvotes: 1