I have a byte[] and i am iterating through a list of ints(and other data) and i want to copy the int to my byteArray[index*4] How do i do this?
BitConverter
is quite possibly your friend.
However, that generally returns you a new byte array. It also doesn't let you specify endianness. I have the EndianBitConverter
class in MiscUtil which has methods to convert primitive types by copying the data directly into an existing byte array.
For instance:
// Copy the bytes from the integer "value" into a byte array
// (buffer) starting at index 5
EndianBitConverter.Little.CopyBytes(value, buffer, 5);
Do it how the BinaryWriter does it:
buffer[0] = (byte) value;
buffer[1] = (byte) (value >> 8);
buffer[2] = (byte) (value >> 0x10);
buffer[3] = (byte) (value >> 0x18);
(obviously this will copy the int into the first 4 bytes of the array)
I'll try to summarize some of the previous answers to make something new
Step 1. As Jon Skeet said before:
BitConverter is quite possibly your friend.
However, that generally returns you a new byte array.
Step 2. You can find the source code of BitConverter.GetBytes(int value) method:
public static unsafe byte[] GetBytes(int value)
{
byte[] numArray = new byte[4];
fixed (byte* numPtr = numArray)
*(int*) numPtr = value;
return numArray;
}
Step 3. Using imagination and changing a few lines in the code from step 2 so it could save the data to an existing array:
public static unsafe byte[] GetBytes(int value, int buffer[], int offset)
{
// Here should be a range check. For example:
// if (offset > buffer.Length + sizeof(int)) throw new IndexOutOfRangeException();
fixed (byte* numPtr = &buffer[offset])
*(int*) numPtr = value;
}
There are many different ways to do it, but to make it nicer, lets use a new feature of c#: extensions.
An integer of the 32 bit variety takes 4 bytes, so it will occupy 4 spots in the byte[]. How do you break an integer in its 4 constituent bytes? You can do it using the bit manipulation operator >>. That operator shifts the bits in the integer by the specified number of bits. For example:
integer = 10399
binary = 00101000 10011111
10399 >> 1 == 0010100 01001111 each bit shifted by 1
Since a byte is 8 bits if we shift the integer by 8 bits we will have the new second byte value of the integer in the right-most bits position
10399 >> 8 = 00000000 00101000
Notice how the second byte is not the first byte and the rest of the bits have been replaced by 0.
We can use this trick to move the bytes into the first position, then force a cast to byte, which will discard the 3 other bytes and will leave us the last bytes value:
(byte)(10399 >> 8) == 0010100
So, using this technique for the 4 bytes will give us access to each one and we will copy them in a destination array that was passed to our new CopyToByteArray method:
public static class Int32Extension
{
public static void CopyToByteArray(this int source, byte[] destination, int offset)
{
if (destination == null)
throw new ArgumentException("Destination array cannot be null");
// check if there is enough space for all the 4 bytes we will copy
if (destination.Length < offset + 4)
throw new ArgumentException("Not enough room in the destination array");
destination[offset] = (byte)(source >> 24); // fourth byte
destination[offset+1] = (byte)(source >> 16); // third byte
destination[offset+2] = (byte)(source >> 8 ); // second byte
destination[offset+3] = (byte)source; // last byte is already in proper position
}
}
Note that we could have copied the bytes in reverse order, that is up to your implementation.
The extension function will allow you to access the new function as a member of the integer class:
int something = 20;
byte[] array = new byte[4];
something.CopyToByteArray(array,0);
Update 2022
A few years have passed since the question was asked. If someone is looking for it today, there is a simpler version with NET 6.
The BinaryPrimitives
class
Write int or other primitives to array
BinaryPrimitives.WriteInt32LittleEndian(array, myInt);
And of course many more methods to write different primitives as Big- or Little-Endian
byte[] bytes = new byte[listOfInts.Count * sizeof(int)];
int pos = 0;
foreach(int i in listOfInts)
{
byte[] b = BitConverter.GetBytes(i);
b.CopyTo(bytes, pos);
pos += b.Length;
}
Buffer.BlockCopy(intArray, 0, byteArray, 0, 4*intArray.Length)
Copies data between two arrays. The last argument is the amount of data to copy in bytes.
Generalizing ADB's exquisit answer:
public static class Int32Extension
{
/// <summary>
/// Copies an int to a byte array: Byte order and sift order are inverted.
/// </summary>
/// <param name="source">The integer to convert.</param>
/// <param name="destination">An arbitrary array of bytes.</param>
/// <param name="offset">Offset into the desination array.</param>
public static void CopyToByteArray(this int source, byte[] destination, int offset)
{
if (destination == null)
throw new ArgumentException("Destination array cannot be null");
// check if there is enough space for all the 4 bytes we will copy
if (destination.Length < offset + sizeof(int))
throw new ArgumentException("Not enough room in the destination array");
for (int i = 0, j = sizeof(int) - 1; i < sizeof(int); i++, --j) {
destination[offset + i] = (byte) (source >> (8 * j));
}
}
/// <summary>
/// Copies an int to a to byte array Little Endian: Byte order and sift order are the same.
/// </summary>
/// <param name="source">The integer to convert.</param>
/// <param name="destination">An arbitrary array of bytes.</param>
/// <param name="offset">Offset into the desination array.</param>
public static void CopyToByteArrayLE(this int source, byte[] destination, int offset)
{
if (destination == null)
throw new ArgumentException("Destination array cannot be null");
// check if there is enough space for all the 4 bytes we will copy
if (destination.Length < offset + sizeof(int))
throw new ArgumentException("Not enough room in the destination array");
for (int i = 0, j = 0; i < sizeof(int); i++, j++) {
destination[offset + i] = (byte) (source >> (8 * j));
}
}
}
© 2022 - 2024 — McMap. All rights reserved.