BitConverter.GetBytes到位

时间:2014-04-14 10:04:04

标签: c# arrays byte

我需要将UInt16UInt64中的值设为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;
}

哪种方法可以实现这一目标?

更新:我不能使用不安全的代码。它不应该创建新的数组实例。

5 个答案:

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