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

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

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 ]

6 голосов
/ 27 марта 2010

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

    byte[] ToBytes() {
        var ms = new MemoryStream(somelength);
        var bw = new BinaryWriter(ms);
        bw.Write(SomeShort);
        bw.Write(SomeOtherShort);
        return ms.ToArray();
    }
3 голосов
/ 27 марта 2010

Вам не нужно инициализировать 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();
1 голос
/ 27 марта 2010

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

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

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

1 голос
/ 27 марта 2010

Если вы заранее знаете размер (имеете набор типов значений), вы можете использовать структуру и присваивать свои значения в структуре. Затем используйте код 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;
}
0 голосов
/ 27 марта 2010

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

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

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

...