Convert byte array to collection of enums in C# - c#

I have a byte array that recevies enums in little endianess byte order from a function GetData() and I want to convert the array into a collection of enums.
How would I copy and cast the bytes in LE order to the enum values in C#? I have a C++ background and not too familiar with the language.
This is a sample code snippet:
public enum BarID
{
TAG0 = 0x0B01,
TAG1 = 0x0B02,
}
public class TestClass
{
List<BarID> ids;
internal TestClass()
{
ids = new List<BarID>();
byte[] foo = GetData(); // returns 01 0b 00 00 02 0b 00 00
// cast byte array so that ids contains the enums 'TAG0' and 'TAG1'
}
}

The interesting step here is reading the bytes reliably in a little-endian way (where "reliable" here means "works on any CPU, not just one that happens to be little-endian itself"); fortunately, BinaryPrimitives makes this obvious, giving you an int from a Span<byte> (the byte[] from GetData() is implicitly castable to Span<byte>). Then from the int you can just cast to BarID:
Span<byte> foo = GetData();
var result = new BarID[foo.Length / 4];
for (int i = 0; i < result.Length; i++)
{
result[i] = (BarID)BinaryPrimitives.ReadInt32LittleEndian(foo.Slice(4 * i));
}
The Slice step here just offsets where we should start reading in the span.

Though Marc's answer is both good and fast, that works only on .NET Core, or if you use additional nugets. If that could be a problem (or you target older Framework versions) you can use a solution like this:
var bytes = new byte[] { 0x01, 0x0b, 0x00, 0x00, 0x02, 0x0b, 0x00, 0x00 };
return BitConverter.IsLittleEndian
? ConvertLittleEndian(bytes)
: ConvertBigEndian(bytes);
Where the conversion methods:
private static unsafe BarID[] ConvertLittleEndian(byte[] bytes)
{
var barIds = new BarID[bytes.Length / 4];
fixed (byte* pBytes = bytes)
{
BarID* asIds = (BarID*)pBytes;
for (int i = 0; i < barIds.Length; i++)
barIds[i] = asIds[i];
}
return barIds;
}
If you know that your code will be used on little endian CPUs (eg. it is meant to be a Windows app), then you don't even need the big endian version:
private static BarID[] ConvertBigEndian(byte[] bytes)
{
var barIds = new BarID[bytes.Length / 4];
for (int i = 0; i < barIds.Length; i++)
{
int offset = i * 4;
barIds[i] = (BarID)((bytes[offset] << 3) | (bytes[offset + 1] << 2)
| (bytes[offset + 2] << 1) | bytes[offset + 3]);
}
return barIds;
}

Try this:
var foo = new byte[] {0x01, 0x0b, 0x00, 0x00, 0x02, 0x0b, 0x00, 0x00}.ToList();
IEnumerable<byte> bytes;
var result = new List<BarID>();
while ((bytes = foo.Take(4)).Any())
{
var number = BitConverter.IsLittleEndian
? BitConverter.ToInt32(bytes.ToArray(), 0)
: BitConverter.ToInt32(bytes.Reverse().ToArray(), 0);
var enumValue = (BarID) number;
result.Add(enumValue);
foo = foo.Skip(4).ToList();
}

It is not clear if the array values are grouped by two or four, however the pattern is basically the same:
public enum BarID
{
TAG0 = 0x0B01,
TAG1 = 0x0B02,
}
public class TestClass
{
List<BarID> ids;
internal TestClass()
{
ids = new List<BarID>();
byte[] foo = GetData(); // returns 01 0b 00 00 02 0b 00 00
// cast byte array so that ids contains the enums 'TAG0' and 'TAG1'
//create a hash-set with all the enum-valid values
var set = new HashSet<int>(
Enum.GetValues(typeof(BarID)).OfType<int>()
);
//scan the array by 2-bytes
for (int i = 0; i < foo.Length; i += 2)
{
int value = foo[i] + foo[i + 1] << 8;
if (set.Contains(value))
{
ids.Add((BarID)value);
}
}
}
}
The set is not mandatory, but it should prevent invalid values to be casted to a tag. For instance, if the values are word-based, the 00 00 value is invalid.
As final consideration, I wouldn't do similar tasks in a class constructor: better to create the instance, then call a dedicated method to the conversion.

Related

C# Convert Active Directory Hexadecimal to GUID

We are pushing AD objects to a 3rd party vendor where the objectGUID attribute is outputted as hexadecimal, as seen in the Attribute Editor window. We need to be able to convert the hexadecimal back to GUID format so that we can perform lookups against the database.
Is it possible to convert hexadecimal back to GUID format? In all likelihood, the hexadecimal will come back in string format.
Example:
Hexadecimal: EC 14 70 17 FD FF 0D 40 BC 03 71 A8 C5 D9 E3 02
or
Hexadecimal (string): ec147017fdff0d40bc0371a8c5d9e302
GUID: 177014EC-FFFD-400D-BC03-71A8C5D9E302
Update
After accepting the answer, I can validate it using some code from Microsoft See here: Guid.ToByteArray Method
using System;
namespace ConsoleApp3
{
class Program
{
static void Main()
{
// https://stackoverflow.com/questions/56638890/c-sharp-convert-active-directory-hexadecimal-to-guid
byte[] bytearray = StringToByteArray("ec147017fdff0d40bc0371a8c5d9e302");
// https://learn.microsoft.com/en-us/dotnet/api/system.guid.tobytearray?view=netframework-4.8
Guid guid = new Guid(bytearray);
Console.WriteLine("Guid: {0}", guid);
Byte[] bytes = guid.ToByteArray();
foreach (var byt in bytes)
Console.Write("{0:X2} ", byt);
Console.WriteLine();
Guid guid2 = new Guid(bytes);
Console.WriteLine("Guid: {0} (Same as First Guid: {1})", guid2, guid2.Equals(guid));
Console.ReadLine();
}
public static byte[] StringToByteArray(String hex)
{
int NumberChars = hex.Length;
byte[] bytes = new byte[NumberChars / 2];
for (int i = 0; i < NumberChars; i += 2)
bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
return bytes;
}
}
}
Guid has a constructor which takes a byte array
You can convert the hexadecimal string into a byte array and use that to construct a new Guid.
If you need to know how to convert the hexadecimal string to a byte array, Stack Overflow already has a few answers to that question.
From the accepted answer of that question:
public static byte[] StringToByteArray(String hex)
{
int NumberChars = hex.Length;
byte[] bytes = new byte[NumberChars / 2];
for (int i = 0; i < NumberChars; i += 2)
bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
return bytes;
}

How to convert decimal string value to hex byte array in C#?

I have an input string which is in decimal format:
var decString = "12345678"; // in hex this is 0xBC614E
and I want to convert this to a fixed length hex byte array:
byte hexBytes[] // = { 0x00, 0x00, 0xBC, 0x61, 0x4E }
I've come up with a few rather convoluted ways to do this but I suspect there is a neat two-liner! Any thoughts? Thanks
UPDATE:
OK I think I may have inadvertently added a level of complexity by having the example showing 5 bytes. Maximum is in fact 4 bytes (FF FF FF FF) = 4294967295. Int64 is fine.
If you have no particular limit to the size of your integer, you could use BigInteger to do this conversion:
var b = BigInteger.Parse("12345678");
var bb = b.ToByteArray();
foreach (var s in bb) {
Console.Write("{0:x} ", s);
}
This prints
4e 61 bc 0
If the order of bytes matters, you may need to reverse the array of bytes.
Maximum is in fact 4 bytes (FF FF FF FF) = 4294967295
You can use uint for that - like this:
uint data = uint.Parse("12345678");
byte[] bytes = new[] {
(byte)((data>>24) & 0xFF)
, (byte)((data>>16) & 0xFF)
, (byte)((data>>8) & 0xFF)
, (byte)((data>>0) & 0xFF)
};
Demo.
To convert the string to bytes you can use BitConverter.GetBytes:
var byteArray = BitConverter.GetBytes(Int32.Parse(decString)).Reverse().ToArray();
Use the appropriate type instead of Int32 if the string is not allways an 32 bit integer.
Then you could check the lenght and add padding bytes if needed:
if (byteArray.Length < 5)
{
var newArray = new byte[5];
Array.Copy(byteArray, 0, newArray, 5 - byteArray.Length, byteArray.Length);
byteArray = newArray;
}
You can use Linq:
String source = "12345678";
// "BC614E"
String result = String.Join("", BigInteger
.Parse(source)
.ToByteArray()
.Reverse()
.SkipWhile(item => item == 0)
.Select(item => item.ToString("X2")));
In case you want Byte[] it'll be
// [0xBC, 0x61, 0x4E]
Byte[] result = BigInteger
.Parse(source)
.ToByteArray()
.Reverse()
.SkipWhile(item => item == 0)
.ToArray();

Dotnet Hex string to Java

Have a problem, much like this post: How to read a .NET Guid into a Java UUID.
Except, from a remote svc I get a hex str formatted like this: ABCDEFGH-IJKL-MNOP-QRST-123456.
I need to match the GUID.ToByteArray() generated .net byte array GH-EF-CD-AB-KL-IJ-OP-MN- QR- ST-12-34-56 in Java for hashing purposes.
I'm kinda at a loss as to how to parse this. Do I cut off the QRST-123456 part and perhaps use something like the Commons IO EndianUtils on the other part, then stitch the 2 arrays back together as well? Seems way too complicated.
I can rearrange the string, but I shouldn't have to do any of these. Mr. Google doesn't wanna help me neither..
BTW, what is the logic in Little Endian land that keeps those last 6 char unchanged?
Yes, for reference, here's what I've done {sorry for 'answer', but had trouble formatting it properly in comment}:
String s = "3C0EA2F3-B3A0-8FB0-23F0-9F36DEAA3F7E";
String[] splitz = s.split("-");
String rebuilt = "";
for (int i = 0; i < 3; i++) {
// Split into 2 char chunks. '..' = nbr of chars in chunks
String[] parts = splitz[i].split("(?<=\\G..)");
for (int k = parts.length -1; k >=0; k--) {
rebuilt += parts[k];
}
}
rebuilt += splitz[3]+splitz[4];
I know, it's hacky, but it'll do for testing.
Make it into a byte[] and skip the first 3 bytes:
package guid;
import java.util.Arrays;
public class GuidConvert {
static byte[] convertUuidToBytes(String guid) {
String hexdigits = guid.replaceAll("-", "");
byte[] bytes = new byte[hexdigits.length()/2];
for (int i = 0; i < bytes.length; i++) {
int x = Integer.parseInt(hexdigits.substring(i*2, (i+1)*2), 16);
bytes[i] = (byte) x;
}
return bytes;
}
static String bytesToHexString(byte[] bytes) {
StringBuilder buf = new StringBuilder();
for (byte b : bytes) {
int i = b >= 0 ? b : (int) b + 256;
buf.append(Integer.toHexString(i / 16));
buf.append(Integer.toHexString(i % 16));
}
return buf.toString();
}
public static void main(String[] args) {
String guid = "3C0EA2F3-B3A0-8FB0-23F0-9F36DEAA3F7E";
byte[] bytes = convertUuidToBytes(guid);
System.err.println("GUID = "+ guid);
System.err.println("bytes = "+ bytesToHexString(bytes));
byte[] tail = Arrays.copyOfRange(bytes, 3, bytes.length);
System.err.println("tail = "+ bytesToHexString(tail));
}
}
The last group of 6 bytes is not reversed because it is an array of bytes. The first four groups are reversed because they are a four-byte integer followed by three two-byte integers.

How to convert an int[,] to byte[] in C#

How to convert an int[,] to byte[] in C#?
Some code will be appreciated
EDIT:
I need a function to perform the following:
byte[] FuncName (int[,] Input)
Since there is very little detail in your question, I can only guess what you're trying to do... Assuming you want to "flatten" a 2D array of ints into a 1D array of bytes, you can do something like that :
byte[] Flatten(int[,] input)
{
return input.Cast<int>().Select(i => (byte)i).ToArray();
}
Note the call to Cast : that's because multidimensional arrays implement IEnumerable but not IEnumerable<T>
It seem that you are writing the types wrong, but here is what you might be looking for:
byte[] FuncName (int[,] input)
{
byte[] byteArray = new byte[input.Length];
int idx = 0;
foreach (int v in input) {
byteArray[idx++] = (byte)v;
}
return byteArray;
}
Here's an implementation that assumes you are attempting serialization; no idea if this is what you want, though; it prefixes the dimensions, then each cell using basic encoding:
public byte[] Encode(int[,] input)
{
int d0 = input.GetLength(0), d1 = input.GetLength(1);
byte[] raw = new byte[((d0 * d1) + 2) * 4];
Buffer.BlockCopy(BitConverter.GetBytes(d0), 0, raw, 0, 4);
Buffer.BlockCopy(BitConverter.GetBytes(d1), 0, raw, 4, 4);
int offset = 8;
for(int i0 = 0 ; i0 < d0 ; i0++)
for (int i1 = 0; i1 < d1; i1++)
{
Buffer.BlockCopy(BitConverter.GetBytes(input[i0,i1]), 0,
raw, offset, 4);
offset += 4;
}
return raw;
}
The BitConverter converts primitive types to byte arrays:
byte[] myByteArray = System.BitConverter.GetBytes(myInt);
You appear to want a 2 dimensional array of ints to be converted to bytes. Combine the BitConverter with the requisite loop construct (e.g foreach) and whatever logic you want to combine the array dimensions.

How to convert a String to a Hex Byte Array? [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
How do you convert Byte Array to Hexadecimal String, and vice versa, in C#?
For testing my encryption algorithm I have being provided keys, plain text and their resulting cipher text.
The keys and plaintext are in strings
How do i convert it to a hex byte array??
Something like this : E8E9EAEBEDEEEFF0F2F3F4F5F7F8F9FA
To something like this :
byte[] key = new byte[16] { 0xE8, 0xE9, 0xEA, 0xEB, 0xED, 0xEE, 0xEF, 0xF0, 0xF2, 0xF3, 0xF4, 0xF5, 0xF7, 0xF8, 0xF9, 0xFA} ;
Thanx in advance :)
Do you need this?
static class HexStringConverter
{
public static byte[] ToByteArray(String HexString)
{
int NumberChars = HexString.Length;
byte[] bytes = new byte[NumberChars / 2];
for (int i = 0; i < NumberChars; i += 2)
{
bytes[i / 2] = Convert.ToByte(HexString.Substring(i, 2), 16);
}
return bytes;
}
}
Hope it helps.
Sample code from MSDN:
string hexValues = "48 65 6C 6C 6F 20 57 6F 72 6C 64 21";
string[] hexValuesSplit = hexValues.Split(' ');
foreach (String hex in hexValuesSplit)
{
// Convert the number expressed in base-16 to an integer.
int value = Convert.ToInt32(hex, 16);
// Get the character corresponding to the integral value.
string stringValue = Char.ConvertFromUtf32(value);
char charValue = (char)value;
Console.WriteLine("hexadecimal value = {0}, int value = {1}, char value = {2} or {3}", hex, value, stringValue, charValue);
}
You only have to change it to split the string on every 2 chars instead of on spaces.
did u mean this
StringBuilder Result = new StringBuilder();
string HexAlphabet = "0123456789ABCDEF";
foreach (byte B in Bytes)
{
Result.Append(HexAlphabet[(int)(B >> 4)]);
Result.Append(HexAlphabet[(int)(B & 0xF)]);
}
return Result.ToString();

Categories