Самый простой способ скопировать int в byte[]

У меня есть byte[], и я перебираю список целых чисел (и других данных), и я хочу скопировать int в свой byteArray[index*4]. Как мне это сделать?


person Community    schedule 17.08.2009    source источник


Ответы (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);
person Jon Skeet    schedule 17.08.2009
comment
вау, каждый день узнаешь что-то новое :) Даже не знал, что такое существует! - person Gareth; 17.08.2009
comment
Согласен, лучше, чем подход сдвига, потому что вам не нужно думать о порядке байтов. (Если, конечно, ему не нужно его менять). - person Noon Silk; 17.08.2009

Сделайте это так, как это делает BinaryWriter:

buffer[0] = (byte) value;
buffer[1] = (byte) (value >> 8);
buffer[2] = (byte) (value >> 0x10);
buffer[3] = (byte) (value >> 0x18);

(очевидно, это скопирует int в первые 4 байта массива)

person Gareth    schedule 17.08.2009

Я попытаюсь обобщить некоторые из предыдущих ответов, чтобы сделать что-то новое

Шаг 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;
}
person SLenik    schedule 24.11.2012
comment
Шаги 2 и 3 выглядят как зависимые от Endian. Не могли бы вы подтвердить? - person Ayyappa; 22.09.2018
comment
Да, оба шага зависят от Endian. - person SLenik; 29.09.2018
comment
Если мы используем операторы сдвига битов, тогда это может быть независимый от байтов код? - person Ayyappa; 29.09.2018

Есть много разных способов сделать это, но чтобы было удобнее, давайте воспользуемся новой функцией 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);
person ADB    schedule 17.08.2009

Buffer.BlockCopy(intArray, 0, byteArray, 0, 4*intArray.Length)

Копирует данные между двумя массивами. Последний аргумент — это количество копируемых данных в байтах.

person Marcus Andrén    schedule 17.08.2009

Обобщая изысканный ответ АБР:

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));
        }
    }
}
person Barton    schedule 16.11.2014