Есть ли менее болезненный способ GetBytes для буфера, не начинающегося с 0?

Мне приходится иметь дело с необработанными байтами в проекте, и мне нужно сделать что-то вроде этого

byte[] ToBytes(){
  byte[] buffer=new byte[somelength];
  byte[] tmp;
  tmp=BitConverter.GetBytes(SomeShort);
  buffer[0]=tmp[0];
  buffer[1]=tmp[1];
  tmp=BitConverter.GetBytes(SomeOtherShort);
  buffer[2]=tmp[0];
  buffer[3]=tmp[1];
}

Я чувствую, что это так неправильно, но я не могу найти лучшего способа сделать это. Есть ли более простой способ?

5 ответов

Решение

BinaryWriter очень эффективен:

    byte[] ToBytes() {
        var ms = new MemoryStream(somelength);
        var bw = new BinaryWriter(ms);
        bw.Write(SomeShort);
        bw.Write(SomeOtherShort);
        return ms.ToArray();
    }

Вам не нужно инициализировать tmp в новый массив. BitConverter.GetBytes создает новый массив и возвращает его для вас. Там не так много вы можете сделать GetBytes но вы можете использовать такие методы, как Buffer.BlockCopy упростить операцию копирования.

Если вы не делаете это в части кода, критически важном для производительности, вы можете использовать LINQy и делать такие вещи:

IEnumerable<byte> bytes = BitConverter.GetBytes(first);
bytes = bytes.Concat(BitConverter.GetBytes(second));
bytes = bytes.Concat(BitConverter.GetBytes(third));
// ... so on; you can chain the calls too
return bytes.ToArray();

Просто сдвиг...

buffer[0]=(byte)SomeShort;
buffer[1]=(byte)(SomeShort >> 8);
buffer[2]=(byte)SomeOtherShort;
buffer[3]=(byte)(SomeOtherShort >> 8);

Это также означает, что вы полностью контролируете порядок байтов (в данном случае, порядок байтов)

Если вы заранее знаете размер (имеете набор типов значений), вы можете использовать структуру и присваивать свои значения в структуре. Тогда используйте unsafe код для копирования необработанных байтов. Я бы все же советовал против этого, если это действительно не нужно для целей скорости. И вы можете подумать, что это больно:)

private struct MyStruct
{
    public short A;
    public short B;

    public MyStruct(short a, short b)
    {
        A = a;
        B = b;
    }
}

private unsafe byte[] UnsafeStruct(MyStruct myStruct)
{
    byte[] buffer = new byte[4]; // where 4 is the size of the struct
    fixed (byte* ptr = buffer)
    {
        *((MyStruct*)ptr) = myStruct;
    }
    return buffer;
}

Вы можете сделать свой код немного короче, используя Array.Copy, но нет никакой перегрузки GetBytes или аналога в BitConverter, который помещает байты непосредственно в ваш буфер.

Может быть, BinaryWriter на MemoryStream - это то, что вы хотите?

Обратите внимание, что, приняв соглашения API BitConverter, которые вам не нравятся, вы создаете ту же проблему для пользователей вашего класса. Вместо этого напишите метод, который принимает BinaryWriter и сериализует в него ваш класс, это прекрасно расширяется, когда ваш класс внедряется в какой-то другой объект.

Другие вопросы по тегам