Comment obtenir des données little endian de big endian en c # en utilisant la méthode bitConverter.ToInt32?

Je fais application dans c # .Dans cette application, j’ai tableau d’octets contenant des valeurs hexadécimales.

Ici, je reçois des données en tant que big endian mais je les veux en tant que petit endian.

Ici, Bitconverter.toInt32 méthode Bitconverter.toInt32 pour convertir cette valeur en entier.

Mais mon problème est qu’avant de convertir une valeur, je dois copier ces données de 4 octets dans un tableau temporaire à partir d’un tableau d’octets source, puis inverser ce tableau d’octets temporaire.

Je ne peux pas inverser le tableau source car il contient également d’autres données.

A cause de cela, mon application devient lente. Code Ici, j’ai un tableau d’octets source en tant que waveData []. Il contient beaucoup de données.

 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); 

Existe-t-il une autre méthode pour cette conversion?

    Si vous savez que les données sont big-endian, faites-le simplement manuellement:

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

    cela fonctionnera également sur n'importe quel processeur. Remarque i est votre décalage actuel dans la mémoire tampon.

    Une autre approche serait de mélanger le tableau:

     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; 

    Je trouve le premier immensément plus lisible, et il n'y a pas de code twigs / complexes, donc ça devrait marcher assez vite aussi. La seconde pourrait également rencontrer des problèmes sur certaines plates-formes (où le processeur exécute déjà le big-endian).

    Dans Linq moderne, la version à une ligne et la plus facile à comprendre serait:

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

    Tu pourrais aussi …

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

    🙂

    Voici

     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; } 

    Déclarez cette classe:

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

    Exemple, créez un formulaire avec un bouton et une zone de texte multiligne:

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

    Si vous n’avez plus jamais besoin de ce tableau temporaire inversé, vous pouvez simplement le créer lorsque vous transmettez le paramètre, au lieu de faire quatre assignations. Par exemple:

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

    Ajoutez une référence à nuget System.Memory et utilisez BinaryPrimitives.ReverseEndianness ().

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

    Il prend en charge les entiers signés et non signés (octet / short / int / long).

    J’utilise les fonctions d’assistance suivantes

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