¿Cómo obtener datos pequeños de endian de big endian en c # usando el método bitConverter.ToInt32?

Estoy haciendo la aplicación en c #. En esa aplicación tengo una matriz de bytes que contiene valores hexadecimales.

Aquí estoy obteniendo datos como un gran endian pero lo quiero como un pequeño endian.

Aquí estoy usando el método Bitconverter.toInt32 para convertir ese valor a entero.

Pero mi problema es que antes de convertir el valor, tengo que copiar los datos de 4 bytes en una matriz temporal de la matriz de bytes de origen y luego invertir la matriz de bytes temporal.

No puedo invertir la matriz de origen porque contiene otros datos también.

Por eso mi aplicación se vuelve lenta. Aquí tengo una matriz fuente de bytes como waveData []. Contiene gran cantidad de datos.

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

¿Hay algún otro método para esa conversión?

Si sabes que la información es big-endian, quizás solo hazlo manualmente:

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

esto funcionará de manera confiable en cualquier CPU, también. Tenga en cuenta que es su desplazamiento actual en el búfer.

Otro enfoque sería mezclar la matriz:

 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; 

Encuentro que el primero es mucho más legible y no hay twigs / código complejo, por lo que debería funcionar bastante rápido también. El segundo también podría tener problemas en algunas plataformas (donde la CPU ya está ejecutando big-endian).

En la moderna Linq, la versión de una sola línea y más fácil de entender sería:

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

También podrías …

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

🙂

Aqui tienes

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

Declara esta clase:

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

Ejemplo, cree un formulario con un botón y un cuadro de texto de líneas múltiples:

 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... 

Si nunca volverá a necesitar esa matriz temporal invertida, podría simplemente crearla al pasar el parámetro, en lugar de hacer cuatro asignaciones. Por ejemplo:

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

Agregue una referencia a System.Memory nuget y use BinaryPrimitives.ReverseEndianness ().

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

Admite los enteros con y sin signo (byte / short / int / long).

Yo uso las siguientes funciones auxiliares

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