2011-11-23 24 views
20

estoy haciendo la aplicación en C# .En esa aplicación tengo una matriz de bytes que contiene valores hexadecimales.¿Cómo obtener datos pequeños de endian de big endian en C# usando el método bitConverter.ToInt32?

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

Aquí estoy usando Bitconverter.toInt32 método 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 la matriz temporal de la matriz de bytes de origen y luego invertir esa matriz de bytes temporal.

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

Por eso mi aplicación se vuelve lenta. Código 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?

Respuesta

19

Si conoce los datos son big-endian, tal vez sólo lo hacen de forma manual:

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

esto va a funcionar de forma fiable en cualquier CPU, también. La nota i es su compensación actual en el búfer.

Otro enfoque sería para 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 el primer inmensamente más fácil de leer, y no hay ramas/código complejo, así 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).

11

Aquí tiene

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

En el día de hoy en el LINQ de una sola línea y más fácil de entender versión sería:

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

Usted también podría ...

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

:)

+4

La primera forma no funcionó para mí sin un '.ToArray()' 'después de Retroceso()'. – heltonbiker

4

Declara esta clase:

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

ejemplo, puede crear un formulario con un botón y un cuadro de texto de varias líneas:

//Some code... 
using BigEndianExtension; 
//Some code... 
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... 
1

Si no va a necesitar nunca más que invierte, matriz temporal, sólo podría crearlo a medida que pasa 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); 
0

utilizo las siguientes funciones de ayuda

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