I've a List with either 1, 2 or 4 hex values saved as decimal values. I want to convert them into one decimal number.
Example:
List<Byte> values: 1 and 95 (= 0x01, 0x5F)
I want to convert the list into one decimal number:
0x015F = 351
How can I do that?
var result = 0;
var i = 0;
foreach (var val in values)
{
result = (result << i) + (int)val;
i += 8;
}
Modern, LINQ-based way (old-fashined C-programmers can turn in one's grave):
List<Byte> list = new List<byte>() { 0x01, 0x5F };
var output = list.Select(x => (int)x)
.Reverse()
.Aggregate((x, y) => (int)0x100 * y + (int)x);
With BitConverter class, you can do:
var values = new List<byte> { 0x01, 0x5F, };
byte[] arr = new byte[4];
for (int i = 0; i < values.Count; ++i)
arr[values.Count - 1 - i] = values[i];
int result = BitConverter.ToInt32(arr, 0);
You fill the array arr backwards from the middle, as seen.
If the numbers can be greater (i.e. the List<> can be up to 8 bytes long), use ulong (never negative), for example:
var values = new List<byte> { 0x01, 0x5F, };
byte[] arr = new byte[8];
for (int i = 0; i < values.Count; ++i)
arr[values.Count - 1 - i] = values[i];
ulong result = BitConverter.ToUInt64(arr, 0);
If the List<> can be arbitrarily long, use new BigInteger(arr) (requires csproj reference to System.Numerics.dll assembly).
Related
This question already has answers here:
How do you convert a byte array to a hexadecimal string, and vice versa?
(53 answers)
Closed 5 years ago.
Can we convert a hex string to a byte array using a built-in function in C# or do I have to make a custom method for this?
Here's a nice fun LINQ example.
public static byte[] StringToByteArray(string hex) {
return Enumerable.Range(0, hex.Length)
.Where(x => x % 2 == 0)
.Select(x => Convert.ToByte(hex.Substring(x, 2), 16))
.ToArray();
}
I did some research and found out that byte.Parse is even slower than Convert.ToByte.
The fastest conversion I could come up with uses approximately 15 ticks per byte.
public static byte[] StringToByteArrayFastest(string hex) {
if (hex.Length % 2 == 1)
throw new Exception("The binary key cannot have an odd number of digits");
byte[] arr = new byte[hex.Length >> 1];
for (int i = 0; i < hex.Length >> 1; ++i)
{
arr[i] = (byte)((GetHexVal(hex[i << 1]) << 4) + (GetHexVal(hex[(i << 1) + 1])));
}
return arr;
}
public static int GetHexVal(char hex) {
int val = (int)hex;
//For uppercase A-F letters:
//return val - (val < 58 ? 48 : 55);
//For lowercase a-f letters:
//return val - (val < 58 ? 48 : 87);
//Or the two combined, but a bit slower:
return val - (val < 58 ? 48 : (val < 97 ? 55 : 87));
}
// also works on .NET Micro Framework where (in SDK4.3) byte.Parse(string) only permits integer formats.
The following code changes the hexadecimal string to a byte array by parsing the string byte-by-byte.
public static byte[] ConvertHexStringToByteArray(string hexString)
{
if (hexString.Length % 2 != 0)
{
throw new ArgumentException(String.Format(CultureInfo.InvariantCulture, "The binary key cannot have an odd number of digits: {0}", hexString));
}
byte[] data = new byte[hexString.Length / 2];
for (int index = 0; index < data.Length; index++)
{
string byteValue = hexString.Substring(index * 2, 2);
data[index] = byte.Parse(byteValue, NumberStyles.HexNumber, CultureInfo.InvariantCulture);
}
return data;
}
I think this may work.
public static byte[] StrToByteArray(string str)
{
Dictionary<string, byte> hexindex = new Dictionary<string, byte>();
for (int i = 0; i <= 255; i++)
hexindex.Add(i.ToString("X2"), (byte)i);
List<byte> hexres = new List<byte>();
for (int i = 0; i < str.Length; i += 2)
hexres.Add(hexindex[str.Substring(i, 2)]);
return hexres.ToArray();
}
I have a group of integers that I want to send over a socket connection. What would be the cleanest way to convert the following variables into a byte array?
int var1 = 1;
int var2 = 2;
int var3 = 3;
Because I'm sending data via sockets, I would like to format the data using big-endianness. Thus for the three variables listed, I would want a 12 byte array such that
byte[0] = 0;
byte[1] = 0;
byte[2] = 0;
byte[3] = 1;
byte[4] = 0;
byte[5] = 0;
byte[6] = 0;
byte[7] = 2;
byte[8] = 0;
byte[9] = 0;
byte[10] = 0;
byte[11] = 3;
My search results are surprisingly coming up empty.
Edit: The suggested duplicate questions are different from what I'm asking. I do not have an "array of integers" or "a single integer" that I want to convert to a byte array. I have a group of individual array variables and am looking for the cleanest solution.
One way to do this would be to write a method that takes in a params int[] arg, which allows you to pass any number of int values to it.
Then you can create a byte[] based on the number of arguments, and populate it in a loop.
Since you want a Big-Endian result, we can use Array.Reverse to reverse the order of bytes returned from BitConverter.GetBytes for each argument, and then we can add each byte to the result array based on the index of the byte and the index of the argument:
public static byte[] GetBigEndianBytes(params int[] args)
{
var result = new byte[args.Length * sizeof(int)];
for (var argIndex = 0; argIndex < args.Length; argIndex++)
{
var bytes = BitConverter.GetBytes(args[argIndex]).Reverse().ToArray();
for (var byteIndex = 0; byteIndex < bytes.Length; byteIndex++)
{
result[byteIndex + argIndex * sizeof(int)] = bytes[byteIndex];
}
}
return result;
}
In use, this might look like:
private static void Main()
{
int var1 = 1;
int var2 = 2;
int var3 = 3;
var result = GetBigEndianBytes(var1, var2, var3);
// result = { 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3}
I use the following to shuffle my byte arrays which is working great and it preserves the indecies of the original order.
because i want to write a deshuffle method, which returns the items to the same order the were in before shuffling, to do this i need to record the indecies before shuffeling so i did the following
public static Random rnd=new Random();
public static void Shuffle(this byte[] Bytes,out int[] indecies)
{
var list = Bytes.Select((b, i) => new Tuple<int, byte>(i, b)).ToArray();
int n = list.Length;
while (n > 1)
{
n--;
int k = rnd.Next(n + 1);
Tuple<int, byte> value = list[k];
list[k] = list[n];
list[n] = value;
}
Bytes = list.Select(tuple => tuple.Item2).ToArray();
indecies = list.Select(tuple => tuple.Item1).ToArray();
}
i am not sure if its the best way but could anyone suggest a way to avoid creating Tuple or creating an object?
Why not simply create another, shuffled array, and keep original array? That even will take less memory, than keeping array of integer indexes.
public static byte[] ToShuffledArray(this byte[] bytes)
{
return bytes.OrderBy(b => rnd.Next()).ToArray();
}
Usage:
byte[] array = { 1, 2, 3, 4, 5 };
byte[] shuffledArray = array.ToShuffledArray();
No output parameters, no integer array of indexes.
if anyone wants it the c way then here it is
var indecies =new byte[Bytes.Length];
for (byte i = 0; i < Bytes.Length; i++)
{
indecies[i] = i;
}
int n = Bytes.Length;
while (n > 1)
{
n--;
int k = ThreadSafeRandom.ThisThreadsRandom.Next(n + 1);
byte value = Bytes[k];
byte index = indecies[k];
Bytes[k] = Bytes[n];
indecies[k] = indecies[n];
Bytes[n] = value;
indecies[n] = index;
}
I have a byte array of
byte[] d = new byte[64];
now i want to convert it to a 2d byte array like ..
byte[,] data = new byte[8,8];
can any one help me on this
This could be one of method.
byte[] d = new byte[64];
byte[,] data = new byte[8,8];
int row = 0;
int column = 0;
for(i=0; i < d.Length; i++)
{
row = i%8;
column = i/8;
data [row, column] = d[i];
}
You can use the Buffer.BlockCopy Method:
byte[] d = new byte[64];
byte[,] data = new byte[8,8];
Buffer.BlockCopy(d, 0, data, 0, 64);
How about something like
byte[] d = new byte[64];
for (byte i = 0; i < d.Length; i++)
d[i] = i;
byte[,] data = new byte[8, 8];
Enumerable.Range(0, 8).ToList().
ForEach(i => Enumerable.Range(0, 8).ToList().
ForEach(j => data[i, j] = d[i * 8 + j]));
How do you convert a string such as "01110100011001010111001101110100" to a byte array then used File.WriteAllBytes such that the exact binary string is the binary of the file. In this case it would be the the text "test".
In case you don't have this LINQ fetish, so common lately, you can try the normal way
string input ....
int numOfBytes = input.Length / 8;
byte[] bytes = new byte[numOfBytes];
for(int i = 0; i < numOfBytes; ++i)
{
bytes[i] = Convert.ToByte(input.Substring(8 * i, 8), 2);
}
File.WriteAllBytes(fileName, bytes);
LINQ is great but there must be some limits.
You could start by splitting the string into a sequence of 8-character strings, then convert those strings to bytes, and eventually write the bytes to a file
string input = "01110100011001010111001101110100";
var bytesAsStrings =
input.Select((c, i) => new { Char = c, Index = i })
.GroupBy(x => x.Index / 8)
.Select(g => new string(g.Select(x => x.Char).ToArray()));
byte[] bytes = bytesAsStrings.Select(s => Convert.ToByte(s, 2)).ToArray();
File.WriteAllBytes(fileName, bytes);
EDIT: here's another way to split the string into 8-character chunks, perhaps a bit simpler :
int nBytes = (int)Math.Ceiling(input.Length / 8m);
var bytesAsStrings =
Enumerable.Range(0, nBytes)
.Select(i => input.Substring(8 * i, Math.Min(8, input.Length - 8 * i)));
If you know that the length of the string is a multiple of 8, you can make it even simpler :
int nBytes = input.Length / 8;
var bytesAsStrings =
Enumerable.Range(0, nBytes)
.Select(i => input.Substring(8 * i, 8));
A bit late, but here's my 2 cents:
var binaryStr = "01110100011001010111001101110100";
var byteArray = Enumerable.Range(0, int.MaxValue/8)
.Select(i => i*8)
.TakeWhile(i => i < binaryStr.Length)
.Select(i => binaryStr.Substring(i, 8))
.Select(s => Convert.ToByte(s, 2))
.ToArray();
File.WriteAllBytes("C:\temp\test.txt", byteArray);
Actually the answer by #Maciej is not correct. As #Phate01 noticed the numOfBytes is correct only for input length which is a power of 8. The second thing is that the byte array should be populated from n to 0 index not the opposite way. Here's the code example:
var bits = "000011110000001000";
var numOfBytes = (int)Math.Ceiling(bits.Length / 8m);
var bytes = new byte[numOfBytes];
var chunkSize = 8;
for (int i = 1; i <= numOfBytes; i++)
{
var startIndex = bits.Length - 8 * i;
if (startIndex < 0)
{
chunkSize = 8 + startIndex;
startIndex = 0;
}
bytes[numOfBytes - i] = Convert.ToByte(bits.Substring(startIndex, chunkSize), 2);
}
This can be improved to get rid of the if statetment but in this form it's more understandable.
The other answers have you covered, but just for fun I wrote the opposite. Going from the string to the ascii binary representation:
private static string StringToAsciiBin(string s)
{
string output = "";
foreach (char c in s.ToCharArray())
{
for (int i = 128; i >= 1; i /=2)
{
if (((int)c & i) > 0)
{
output += "1";
}
else
{
output += "0";
}
}
}
return output;
}