byte[] があり、int (およびその他のデータ) のリストを反復処理しています。int を byteArray[index*4] にコピーしたいのですが、どうすればよいですか?
7 に答える
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);
BinaryWriter が行う方法を実行します。
buffer[0] = (byte) value;
buffer[1] = (byte) (value >> 8);
buffer[2] = (byte) (value >> 0x10);
buffer[3] = (byte) (value >> 0x18);
(明らかに、これは int を配列の最初の 4 バイトにコピーします)
私は何か新しいものを作るために以前の答えのいくつかを要約しようとします
ステップ1.JonSkeetが前に言ったように:
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#: 拡張機能の新機能を使用してみましょう。
32 ビットの整数は 4 バイトかかるため、byte[] の 4 つの場所を占めます。4 つの構成バイトで整数をどのように分割しますか? ビット操作演算子 >> を使用して実行できます。その演算子は、指定されたビット数だけ整数のビットをシフトします。例えば:
integer = 10399
binary = 00101000 10011111
10399 >> 1 == 0010100 01001111 each bit shifted by 1
1 バイトは 8 ビットであるため、整数を 8 ビットシフトすると、整数の新しい 2 番目のバイト値が右端のビット位置になります。
10399 >> 8 = 00000000 00101000
2 番目のバイトが最初のバイトではなく、残りのビットが 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);
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)
2 つの配列間でデータをコピーします。最後の引数は、コピーするデータの量 (バイト単位) です。
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));
}
}
}