将int复制到byte[]的最简单方法

12

我有一个byte[],我正在遍历int(和其他数据)列表,并且我想将int复制到我的byteArray [索引* 4]中。我该怎么做?

8个回答

22

BitConverter可能是你的好朋友。

然而,它通常会返回一个新的字节数组。它也不允许你指定字节序。我在MiscUtil中有一个EndianBitConverter类,它具有通过将数据直接复制到现有字节数组中来转换基元类型的方法。

例如:

// Copy the bytes from the integer "value" into a byte array
// (buffer) starting at index 5
EndianBitConverter.Little.CopyBytes(value, buffer, 5);

哇,每天都能学到新东西 :) 我甚至不知道那个存在! - Gareth
1
同意,比移位方法更好,因为你不需要考虑字节序问题。(当然,除非他需要改变它)。 - Noon Silk

10

按照BinaryWriter的方式去做:

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

(显然,这将把整数复制到数组的前4个字节中)


这个是否与字节序无关? - undefined

7
我会尽力总结之前的答案,以创造新的内容。 步骤1。Jon Skeet之前所说:

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;
}
第三步。运用想象力并更改第二步中的代码几行,使其能够将数据保存到现有数组中:
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;
}

第二步和第三步似乎与字节序有关。您能否确认一下? - Ayyappa
1
是的,这两个步骤都与字节序有关。 - SLenik
如果我们使用位移操作符,那么它可以成为独立于字节序的代码吗? - Ayyappa

6

有很多方法可以实现,但为了使其更好,请使用c#的一个新功能:扩展。

32位整数需要4个字节,因此在byte[]中占用4个位置。如何将整数分解为其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);

2

2022年更新

自提出该问题以来已经过去了几年。如果今天有人在寻找相关信息,可以使用.NET 6中更简单的版本。

使用BinaryPrimitives

将int或其他基本数据类型写入数组中。

BinaryPrimitives.WriteInt32LittleEndian(array, myInt);

当然,还有许多方法可以编写不同的原语作为大端或小端


1
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;
}

1

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

该方法用于在两个数组之间复制数据。最后一个参数表示要复制的数据量(以字节为单位)。


0

概括ADB的精美答案:

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));
        }
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接