2010-03-27 28 views
6

¿Cómo podría eliminar una cantidad de bytes de una matriz de bytes?¿Quitar los primeros 16 bytes?

+4

Otra pregunta SO defectuosa, hemos estado recibiendo muchas de ellas últimamente. Distinguido por una pregunta de una sola oración que no hace mucho para explicar el título. Con mucho, el mejor enfoque es no hacerlo.Muchos métodos que toman una matriz tienen una sobrecarga que toma una compensación y longitud. Incluso hay una clase dedicada para él: ArraySegment . Ya sea que eso te ayude no está claro a partir de tu pregunta. Probablemente no. –

Respuesta

24

EDIT: Como comentario de nobugz (y la respuesta de Reed Copsey) menciona, si no necesita realmente el resultado como una matriz de bytes, usted debe buscar en el uso de ArraySegment<T>:

ArraySegment<byte> segment = new ArraySegment<byte>(full, 16, full.Length - 16); 

De lo contrario, la copia será Es necesario: las matrices siempre tienen un tamaño fijo, por lo que no puede "eliminar" los primeros 16 bytes de la matriz existente. En su lugar, deberá crear una nueva matriz más pequeña y copiar los datos relevantes en ella.

sugerencia de Zach es en la dirección correcta para el enfoque no LINQ, pero puede ser más sencilla (se asume que ya conoce la matriz original es de al menos 16 bytes de longitud):

byte[] newArray = new byte[oldArray.Length - 16]; 
Buffer.BlockCopy(oldArray, 16, newArray, 0, newArray.Length); 

o

byte[] newArray = new byte[oldArray.Length - 16]; 
Array.Copy(oldArray, 16, newArray, 0, newArray.Length); 

I sospechosoBuffer.BlockCopy habrá un poco más rápido, pero no lo sé a ciencia cierta.

Tenga en cuenta que ambos éstos podrían ser significativamente más eficaz que el enfoque LINQ si las matrices involucradas son grandes: el enfoque LINQ requiere cada byte a devolver individualmente de un iterador, y copias potencialmente intermedios que se hizo (en la misma forma en que agregar elementos a un List<T> necesita hacer crecer periódicamente el conjunto de respaldo). Obviamente no micro-optimize, pero vale comprobando si este bit de código es un cuello de botella de rendimiento.

EDIT: ejecuté un punto de referencia muy "rápido y sucio" de los tres enfoques. No confío en que el punto de referencia distinga entre Buffer.BlockCopy y Array.Copy - estuvieron muy cerca - pero el enfoque LINQ fue más de 100 veces más lento.

En mi computadora portátil, usando matrices de bytes de 10.000 elementos, me llevó casi 10 segundos realizar 40,000 copias con LINQ; los enfoques anteriores tomaron cerca de 80ms para hacer la misma cantidad de trabajo. Aumenté el recuento de iteraciones a 4.000.000 y solo tardó unos 7 segundos. Obviamente, se aplican las advertencias normales sobre los micro-puntos de referencia, pero esta es una diferencia bastante significativa.

Definitivamente el uso del enfoque anterior, si este se encuentra en una ruta de código que es importante para el rendimiento :)

+0

+1, el almacenamiento en búfer es definitivamente más eficiente para matrices grandes. –

+0

¿Cuál es la diferencia entre Buffer.BlockCopy y Array.Copy cuando se usa con matrices de bytes? – dtb

+0

@dtb: no espero que exista ninguna diferencia funcional en este caso. 'Buffer.BlockCopy' es un poco más restrictivo. Sospecho que se implementó en un nivel inferior, pero no conozco los detalles. –

14

Usted puede hacer esto:

using System.Linq 

// ... 

var newArray = oldArray.Skip(numBytes).ToArray(); 
0

Si no puede utilizar LINQ, que podría hacerlo de esta manera:

byte[] myArray = // however you acquire the array 

byte[] newArray = new byte[myArray.Length - 16]; 

for (int i = 0; i < newArray.Length; i++) 
{ 
    newArray[i] = myArray[i + 16]; 
} 

// newArray is now myArray minus the first 16 bytes 

También tendrá que manejar el caso en el que la matriz tiene menos de 16 bytes de longitud.

6

voy a mencionar también - dependiendo de cómo se va a utilizar los resultados, a menudo, un enfoque alternativo es utilizar ArraySegment<T> para acceder a la porción restante de la matriz. Esto evita la necesidad de copiar la matriz, que puede ser más eficiente en algunos escenarios de uso:

ArraySegment<byte> segment = new ArraySegment<byte>(originalArray, 16, originalArray.Length-16); 

// Use segment how you'd use your array... 
Cuestiones relacionadas