Come ottenere dati little endian da big endian in c # usando il metodo bitConverter.ToInt32?

sto facendo applicazione in C #. In quell’applicazione ho array di byte contenente valori esadecimali.

Qui sto ricevendo dati come big endian ma lo voglio come un piccolo endian.

Qui sto usando il metodo Bitconverter.toInt32 per convertire quel valore in numero intero.

Ma il mio problema è che prima di convertire il valore, devo copiare quei dati a 4 byte in una matrice temporanea dall’array di byte sorgente e quindi invertire quella matrice di byte temporanea.

Non posso invertire la matrice di sorgenti perché contiene anche altri dati.

Per questo la mia applicazione diventa lenta. codice Qui ho una matrice sorgente di byte come waveData []. Contiene molti dati.

 byte[] tempForTimestamp=new byte[4]; tempForTimestamp[0] = waveData[290]; tempForTimestamp[1] = waveData[289]; tempForTimestamp[2] = waveData[288]; tempForTimestamp[3] = waveData[287]; int number = BitConverter.ToInt32(tempForTimestamp, 0); 

C’è qualche altro metodo per quella conversione?

Se sai che i dati sono big-endian, forse basta farlo manualmente:

 int value = (buffer[i++] << 24) | (buffer[i++] << 16) | (buffer[i++] << 8) | buffer[i++]; 

questo funzionerà in modo affidabile anche su qualsiasi CPU. Nota i è il tuo attuale offset nel buffer.

Un altro approccio sarebbe quello di mischiare l'array:

 byte tmp = buffer[i+3]; buffer[i+3] = buffer[i]; buffer[i] = tmp; tmp = buffer[i+2]; buffer[i+2] = buffer[i+1]; buffer[i+1] = tmp; int value = BitConverter.ToInt32(buffer, i); i += 4; 

Trovo che il primo sia immensamente più leggibile e non ci siano rami / codice complesso, quindi dovrebbe funzionare anche abbastanza velocemente. Il secondo potrebbe anche incorrere in problemi su alcune piattaforms (dove la CPU sta già eseguendo big-endian).

Nella moderna Linq, la versione one-liner e di facile comprensione sarebbe:

 int number = BitConverter.ToInt32(waveData.Skip(286).Take(4).Reverse().ToArray(), 0); 

Potresti anche …

 byte[] tempForTimestamp = new byte[4]; Array.Copy(waveData, 287, tempForTimestamp, 0, 4); Array.Reverse(tempForTimestamp); int number = BitConverter.ToInt32(tempForTimestamp); 

🙂

Ecco qui

 public static int SwapEndianness(int value) { var b1 = (value >> 0) & 0xff; var b2 = (value >> 8) & 0xff; var b3 = (value >> 16) & 0xff; var b4 = (value >> 24) & 0xff; return b1 << 24 | b2 << 16 | b3 << 8 | b4 << 0; } 

Dichiara questa class:

 using static System.Net.IPAddress; namespace BigEndianExtension { public static class BigEndian { public static short ToBigEndian(this short value) => HostToNetworkOrder(value); public static int ToBigEndian(this int value) => HostToNetworkOrder(value); public static long ToBigEndian(this long value) => HostToNetworkOrder(value); public static short FromBigEndian(this short value) => NetworkToHostOrder(value); public static int FromBigEndian(this int value) => NetworkToHostOrder(value); public static long FromBigEndian(this long value) => NetworkToHostOrder(value); } } 

Esempio, crea un modulo con un pulsante e una casella di testo multilinea:

 using BigEndianExtension; private void button1_Click(object sender, EventArgs e) { short int16 = 0x1234; int int32 = 0x12345678; long int64 = 0x123456789abcdef0; string text = string.Format("LE:{0:X4}\r\nBE:{1:X4}\r\n", int16, int16.ToBigEndian()); text += string.Format("LE:{0:X8}\r\nBE:{1:X8}\r\n", int32, int32.ToBigEndian()); text += string.Format("LE:{0:X16}\r\nBE:{1:X16}\r\n", int64, int64.ToBigEndian()); textBox1.Text = text; } //Some code... 

Se non avrai mai più bisogno di quell’array temporaneo invertito, potresti semplicemente crearlo mentre passi il parametro, invece di fare quattro assegnazioni. Per esempio:

 int i = 287; int value = BitConverter.ToInt32({ waveData(i + 3), waveData(i + 2), waveData(i + 1), waveData(i) }, 0); 

Aggiungi un riferimento a System.Memory nuget e utilizza BinaryPrimitives.ReverseEndianness ().

 using System.Buffers.Binary; number = BinaryPrimitives.ReverseEndianness(number); 

Supporta sia interi firmati che non firmati (byte / short / int / long).

Io uso le seguenti funzioni di supporto

 public static Int16 ToInt16(byte[] data, int offset) { if (BitConverter.IsLittleEndian) return BitConverter.ToInt16(BitConverter.IsLittleEndian ? data.Skip(offset).Take(2).Reverse().ToArray() : data, 0); return BitConverter.ToInt16(data, offset); } public static Int32 ToInt32(byte[] data, int offset) { if (BitConverter.IsLittleEndian) return BitConverter.ToInt32(BitConverter.IsLittleEndian ? data.Skip(offset).Take(4).Reverse().ToArray() : data, 0); return BitConverter.ToInt32(data, offset); } public static Int64 ToInt64(byte[] data, int offset) { if (BitConverter.IsLittleEndian) return BitConverter.ToInt64(BitConverter.IsLittleEndian ? data.Skip(offset).Take(8).Reverse().ToArray() : data, 0); return BitConverter.ToInt64(data, offset); }