我需要将UInt16
和UInt64
中的值设为Byte[]
。目前我正在使用BitConverter.GetBytes
,但这种方法每次都会给我一个新的数组实例。
我想使用一种允许我将这些值“复制”到现有数组的方法,例如:
.ToBytes(UInt64 value, Byte[] array, Int32 offset);
.ToBytes(UInt16 value, Byte[] array, Int32 offset);
我一直在看看使用ILSpy的.NET源代码,但我不太确定这段代码是如何工作的,如何安全地修改它以符合我的要求:
public unsafe static byte[] GetBytes(long value)
{
byte[] array = new byte[8];
fixed (byte* ptr = array)
{
*(long*)ptr = value;
}
return array;
}
哪种方法可以实现这一目标?
更新:我不能使用不安全的代码。它不应该创建新的数组实例。
答案 0 :(得分:6)
你可以这样做:
static unsafe void ToBytes(ulong value, byte[] array, int offset)
{
fixed (byte* ptr = &array[offset])
*(ulong*)ptr = value;
}
用法:
byte[] array = new byte[9];
ToBytes(0x1122334455667788, array, 1);
您只能以字节为单位设置偏移量。
如果您想通过托管方式执行此操作:
static void ToBytes(ulong value, byte[] array, int offset)
{
byte[] valueBytes = BitConverter.GetBytes(value);
Array.Copy(valueBytes, 0, array, offset, valueBytes.Length);
}
或者您可以自己填写值:
static void ToBytes(ulong value, byte[] array, int offset)
{
for (int i = 0; i < 8; i++)
{
array[offset + i] = (byte)value;
value >>= 8;
}
}
答案 1 :(得分:1)
你说你想避免创建新的数组,你不能使用不安全的。使用Ulugbek Umirov对缓存数组的回答(小心线程问题)或:
static void ToBytes(ulong value, byte[] array, int offset) {
unchecked {
array[offset + 0] = (byte)(value >> (8*7));
array[offset + 1] = (byte)(value >> (8*6));
array[offset + 2] = (byte)(value >> (8*5));
array[offset + 3] = (byte)(value >> (8*4));
//...
}
}
答案 2 :(得分:1)
现在,.NET添加了Span<T>
支持以更好地处理数组,非托管内存等,而没有过多的分配,他们还添加了System.Buffer.Binary.BinaryPrimitives。
如您所愿,它可以工作,例如WriteUInt64BigEndian具有以下签名:
public static void WriteUInt64BigEndian (Span<byte> destination, ulong value);
避免分配。
答案 3 :(得分:0)
由于某种原因,您似乎希望避免创建任何临时的新数组。而且你也想避免不安全的代码。
您可以固定对象,然后复制到数组。
public static void ToBytes(ulong value, byte[] array, int offset)
{
GCHandle handle = GCHandle.Alloc(value, GCHandleType.Pinned);
try
{
Marshal.Copy(handle.AddrOfPinnedObject(), array, offset, 8);
}
finally
{
handle.Free();
}
}
答案 4 :(得分:0)
BinaryWriter可能是一个很好的解决方案。
var writer = new BinaryWriter(new MemoryStream(yourbuffer, youroffset, yourbuffer.Length-youroffset));
writer.Write(someuint64);
当您需要将大量数据连续转换为缓冲区时非常有用
var writer = new BinaryWriter(new MemoryStream(yourbuffer));
foreach(var value in yourints){
writer.Write(value);
}
或者当您只想写入文件时,最好使用BinaryWriter。
var writer = new BinaryWriter(yourFileStream);
foreach(var value in yourints){
writer.Write(value);
}