У меня есть byte[], и я перебираю список целых чисел (и других данных), и я хочу скопировать int в свой byteArray[index*4]. Как мне это сделать?
Самый простой способ скопировать int в byte[]
Ответы (6)
BitConverter
вполне возможно, ваш друг.
Однако обычно это возвращает вам новый массив байтов. Это также не позволяет вам указывать порядок следования байтов. У меня есть класс EndianBitConverter
в MiscUtil, в котором есть методы для преобразования примитивных типов путем копирования данных непосредственно в существующий массив байтов.
Например:
// Copy the bytes from the integer "value" into a byte array
// (buffer) starting at index 5
EndianBitConverter.Little.CopyBytes(value, buffer, 5);
Сделайте это так, как это делает BinaryWriter:
buffer[0] = (byte) value;
buffer[1] = (byte) (value >> 8);
buffer[2] = (byte) (value >> 0x10);
buffer[3] = (byte) (value >> 0x18);
(очевидно, это скопирует int в первые 4 байта массива)
Я попытаюсь обобщить некоторые из предыдущих ответов, чтобы сделать что-то новое
Шаг 1. Как сказал ранее Джон Скит:
BitConverter вполне может быть вашим другом.
Однако обычно это возвращает вам новый массив байтов.
Шаг 2. Вы можете найти исходный код метода BitConverter.GetBytes(int value):
public static unsafe byte[] GetBytes(int value)
{
byte[] numArray = new byte[4];
fixed (byte* numPtr = numArray)
*(int*) numPtr = value;
return numArray;
}
Шаг 3. Используя воображение, изменив несколько строк кода из шага 2, чтобы можно было сохранить данные в существующий массив:
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;
}
Есть много разных способов сделать это, но чтобы было удобнее, давайте воспользуемся новой функцией c#: extensions.
Целое число 32-битного типа занимает 4 байта, поэтому оно будет занимать 4 позиции в byte[]. Как разбить целое число на 4 составляющих его байта? Вы можете сделать это с помощью оператора обработки битов >>. Этот оператор сдвигает биты в целом числе на указанное количество битов. Например:
integer = 10399
binary = 00101000 10011111
10399 >> 1 == 0010100 01001111 each bit shifted by 1
Поскольку байт равен 8 битам, если мы сдвинем целое число на 8 бит, мы получим новое значение второго байта целого числа в самой правой битовой позиции.
10399 >> 8 = 00000000 00101000
Обратите внимание, что второй байт не является первым байтом, а остальные биты заменены на 0.
Мы можем использовать этот трюк, чтобы переместить байты в первую позицию, а затем принудительно привести к байту, который отбросит 3 других байта и оставит нам значение последнего байта:
(byte)(10399 >> 8) == 0010100
Таким образом, использование этой техники для 4 байтов даст нам доступ к каждому из них, и мы скопируем их в целевой массив, который был передан нашему новому методу CopyToByteArray:
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
}
}
Обратите внимание, что мы могли бы скопировать байты в обратном порядке, это зависит от вашей реализации.
Функция расширения позволит вам получить доступ к новой функции как к члену целочисленного класса:
int something = 20;
byte[] array = new byte[4];
something.CopyToByteArray(array,0);
Buffer.BlockCopy(intArray, 0, byteArray, 0, 4*intArray.Length)
Копирует данные между двумя массивами. Последний аргумент — это количество копируемых данных в байтах.
Обобщая изысканный ответ АБР:
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));
}
}
}