Existe uma maneira menos dolorosa de getbytes para um buffer que não está começando em 0?
-
22-09-2019 - |
Pergunta
Estou tendo que lidar com bytes crus em um projeto e preciso basicamente fazer algo assim
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];
}
Sinto que isso está tão errado, mas não consigo encontrar nenhuma maneira melhor de fazê -lo. Existe uma maneira mais fácil?
Solução
O BinaryWriter é muito eficiente:
byte[] ToBytes() {
var ms = new MemoryStream(somelength);
var bw = new BinaryWriter(ms);
bw.Write(SomeShort);
bw.Write(SomeOtherShort);
return ms.ToArray();
}
Outras dicas
Você não precisa inicializar tmp
para uma nova matriz. BitConverter.GetBytes
Cria uma nova matriz e a devolve para você. Não há muito que você possa fazer sobre GetBytes
Mas você pode usar métodos como Buffer.BlockCopy
Para simplificar a operação de cópia.
Se você não está fazendo isso em uma peça de código crítica, você pode ficar um pouco linqy e fazer coisas como:
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();
Se você souber o tamanho de antemão (tenha um conjunto de tipos de valor), poderá usar uma estrutura e atribuir seus valores na estrutura. Em seguida, use unsafe
código para copiar os bytes brutos. Eu ainda aconselharia contra, a menos que seja realmente necessário para fins de velocidade. E você pode pensar que é doloroso :)
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;
}
Apenas deslocamento ...
buffer[0]=(byte)SomeShort;
buffer[1]=(byte)(SomeShort >> 8);
buffer[2]=(byte)SomeOtherShort;
buffer[3]=(byte)(SomeOtherShort >> 8);
Isso também significa que você está no controle total do endian-ness (neste caso, Little-Endian)
Você pode tornar seu código um pouco mais curto usando o Array.copy, mas não, não há sobrecarga do GetBytes ou equivalente no BitConverter que coloca os bytes diretamente no seu buffer.
Pode ser BinaryWriter com um MemoryStream é o que você quer?
Observe que, ao adotar as convenções da API do BitConverter que você não gosta, você está causando o mesmo problema para os usuários da sua classe. Em vez disso, escreva um método que aceite um redator de binários e serialize sua classe nele, isso se estende muito bem quando sua classe é incorporada em algum outro objeto.