2009-08-17 12 views

Respuesta

17

BitConverter es posiblemente su amigo.

Sin embargo, eso generalmente le devuelve una nueva matriz de bytes. Tampoco le permite especificar endianness. Tengo la clase EndianBitConverter en MiscUtil que tiene métodos para convertir tipos primitivos copiando los datos directamente en una matriz de bytes existente.

Por ejemplo:

// Copy the bytes from the integer "value" into a byte array 
// (buffer) starting at index 5 
EndianBitConverter.Little.CopyBytes(value, buffer, 5); 
+0

wow, aprendes algo nuevo todos los días :) ¡Ni siquiera sabía que existía! – Gareth

+1

De acuerdo, mejor que el enfoque cambiante, porque no necesita pensar en el endian-ness. (A menos que, por supuesto, él necesite cambiarlo). –

8

Hágalo cómo el BinaryWriter lo hace:

buffer[0] = (byte) value; 
buffer[1] = (byte) (value >> 8); 
buffer[2] = (byte) (value >> 0x10); 
buffer[3] = (byte) (value >> 0x18); 

(obviamente, esto copiará el int en los primeros 4 bytes de la matriz)

0
byte[] bytes = new byte[listOfInts.Count * sizeof(int)]; 
int pos = 0; 
foreach(int i in listOfInts) 
{ 
    byte[] b = BitConverter.GetBytes(i); 
    b.CopyTo(bytes, pos); 
    pos += b.Length; 
} 
1

Buffer.BlockCopy (intArray, 0, byteArray, 0, 4 * intArray.Length)

Copia datos entre dos matrices. El último argumento es la cantidad de datos para copiar en bytes.

6

Hay muchas maneras diferentes de hacerlo, pero para que sea más agradable, use una nueva característica de C#: extensiones.

Un número entero de la variedad de 32 bits toma 4 bytes, por lo que ocupará 4 espacios en el byte []. ¿Cómo se divide un número entero en sus 4 bytes constituyentes? Puedes hacerlo usando el operador de manipulación de bits >>. Ese operador desplaza los bits en el número entero por el número especificado de bits. Por ejemplo:

integer = 10399 
binary = 00101000 10011111 
10399 >> 1 == 0010100 01001111 each bit shifted by 1 

Puesto que un byte es de 8 bits si cambiamos el número entero por 8 bits tendremos el nuevo valor de segundo byte del entero en la posición más a la derecha los bits

10399 >> 8 = 00000000 00101000 

Aviso cómo el segundo byte no es el primer byte y el resto de los bits han sido reemplazados por 0.

Podemos usar este truco para mover los bytes a la primera posición, luego forzar un lanzamiento a byte, que descartará el 3 otros bytes y nos dejará el último valor de bytes:

(byte)(10399 >> 8) == 0010100 

Por lo tanto, el uso de esta técnica para los 4 bytes nos dará acceso a cada uno y los copiará en una matriz de destino que se pasó a nuestro nuevo método CopyToByteArray:

public static class Int32Extension 
{ 
    public static void CopyToByteArray(this int source, byte[] destination, int offset) 
    { 
     if (destination == null) 
      throw new ArgumentException("Destination array cannot be null"); 

     // check if there is enough space for all the 4 bytes we will copy 
     if (destination.Length < offset + 4) 
      throw new ArgumentException("Not enough room in the destination array"); 

     destination[offset] = (byte)(source >> 24); // fourth byte 
     destination[offset+1] = (byte)(source >> 16); // third byte 
     destination[offset+2] = (byte)(source >> 8); // second byte 
     destination[offset+3] = (byte)source; // last byte is already in proper position 
    } 
} 

Tenga en cuenta que podríamos haber copiado los bytes en orden inverso, eso depende de su implementación.

La función de extensión le permitirá acceder a las nuevas funciones como miembro de la clase entero:

int something = 20; 
byte[] array = new byte[4]; 
something.CopyToByteArray(array,0); 
6

voy a tratar de resumir algunas de las respuestas anteriores para hacer algo nuevo

paso 1. ComoJon Skeet dijo antes:

BitConverter es, posiblemente, su amigo.

Sin embargo, eso generalmente le devuelve una nueva matriz de bytes.

Paso 2. Puede encontrar el código fuente de BitConverter.GetBytes (int value) Método:

public static unsafe byte[] GetBytes(int value) 
{ 
    byte[] numArray = new byte[4]; 
    fixed (byte* numPtr = numArray) 
     *(int*) numPtr = value; 
    return numArray; 
} 

Paso 3. El uso de la imaginación y el cambio de unas pocas líneas en el código de paso 2 por lo que podría guardar los datos en una matriz existente:

public static unsafe byte[] GetBytes(int value, int buffer[], int offset) 
{ 
    // Here should be a range check. For example: 
    // if (offset > buffer.Length + sizeof(int)) throw new IndexOutOfRangeException(); 

    fixed (byte* numPtr = &buffer[offset]) 
     *(int*) numPtr = value; 
} 
0

respuesta exquisito de Generalizando ADB:

public static class Int32Extension 
{ 

    /// <summary> 
    /// Copies an int to a byte array: Byte order and sift order are inverted. 
    /// </summary> 
    /// <param name="source">The integer to convert.</param> 
    /// <param name="destination">An arbitrary array of bytes.</param> 
    /// <param name="offset">Offset into the desination array.</param> 
    public static void CopyToByteArray(this int source, byte[] destination, int offset) 
    { 
     if (destination == null) 
      throw new ArgumentException("Destination array cannot be null"); 

     // check if there is enough space for all the 4 bytes we will copy 
     if (destination.Length < offset + sizeof(int)) 
      throw new ArgumentException("Not enough room in the destination array"); 

     for (int i = 0, j = sizeof(int) - 1; i < sizeof(int); i++, --j) { 
      destination[offset + i] = (byte) (source >> (8 * j)); 
     } 
    } 

    /// <summary> 
    /// Copies an int to a to byte array Little Endian: Byte order and sift order are the same. 
    /// </summary> 
    /// <param name="source">The integer to convert.</param> 
    /// <param name="destination">An arbitrary array of bytes.</param> 
    /// <param name="offset">Offset into the desination array.</param> 
    public static void CopyToByteArrayLE(this int source, byte[] destination, int offset) 
    { 
     if (destination == null) 
      throw new ArgumentException("Destination array cannot be null"); 

     // check if there is enough space for all the 4 bytes we will copy 
     if (destination.Length < offset + sizeof(int)) 
      throw new ArgumentException("Not enough room in the destination array"); 

     for (int i = 0, j = 0; i < sizeof(int); i++, j++) { 
      destination[offset + i] = (byte) (source >> (8 * j)); 
     } 
    } 
} 
Cuestiones relacionadas