¿Cuál es la forma fácil de concatenar dos byte
matrices?
Decir,
byte a[];
byte b[];
¿Cómo concateno dos byte
matrices y las almaceno en otra byte
matriz?
¿Cuál es la forma fácil de concatenar dos byte
matrices?
Decir,
byte a[];
byte b[];
¿Cómo concateno dos byte
matrices y las almaceno en otra byte
matriz?
Respuestas:
La forma más elegante de hacer esto es con un ByteArrayOutputStream
.
byte a[];
byte b[];
ByteArrayOutputStream outputStream = new ByteArrayOutputStream( );
outputStream.write( a );
outputStream.write( b );
byte c[] = outputStream.toByteArray( );
outputStream.write( c );
; no tiene que volver atrás y editar la línea donde crea la matriz de bytes de resultado. Además, reordenar las matrices es simple, a diferencia del uso del método arraycopy.
a.length + b.length
como argumento para el ByteArrayOutputStream
constructor. Tenga en cuenta que este método todavía copiará todos los bytes a una nueva matriz para asignarlos c[]
. Considere el ByteBuffer
método como un competidor cercano, que no desperdicie memoria.
He aquí una buena solución usando la guayaba 's com.google.common.primitives.Bytes
:
byte[] c = Bytes.concat(a, b);
Lo mejor de este método es que tiene una firma varargs:
public static byte[] concat(byte[]... arrays)
lo que significa que puede concatenar un número arbitrario de matrices en una sola llamada de método.
Otra posibilidad es usar java.nio.ByteBuffer
.
Algo como
ByteBuffer bb = ByteBuffer.allocate(a.length + b.length + c.length);
bb.put(a);
bb.put(b);
bb.put(c);
byte[] result = bb.array();
// or using method chaining:
byte[] result = ByteBuffer
.allocate(a.length + b.length + c.length)
.put(a).put(b).put(c)
.array();
Tenga en cuenta que la matriz debe tener el tamaño adecuado para comenzar, por lo que se requiere la línea de asignación (ya que array()
simplemente devuelve la matriz de respaldo, sin tener en cuenta el desplazamiento, la posición o el límite).
ByteBuffer.allocate(int)
es un método estático que devuelve una instancia java.nio.HeapByteBuffer
, una subclase de ByteBuffer
. Se atiende a los métodos .put()
y .compact()
, y a cualquier otra abstracción.
compact()
línea porque es incorrecta.
bb.flip(); bb.get(result);
en lugar de la byte[] result = bb.array();
línea.
allocate
método revela lo siguiente: "La posición del nuevo buffer será cero, su límite será su capacidad, su marca será indefinida y cada uno de sus elementos se inicializará a cero . Tendrá una matriz de respaldo y su compensación de matriz será cero ". Entonces, para este fragmento de código en particular , donde ByteBuffer
se asigna internamente, no es un problema.
Otra forma es usar una función de utilidad (si lo desea, puede hacer que sea un método estático de una clase de utilidad genérica):
byte[] concat(byte[]...arrays)
{
// Determine the length of the result array
int totalLength = 0;
for (int i = 0; i < arrays.length; i++)
{
totalLength += arrays[i].length;
}
// create the result array
byte[] result = new byte[totalLength];
// copy the source arrays into the result array
int currentIndex = 0;
for (int i = 0; i < arrays.length; i++)
{
System.arraycopy(arrays[i], 0, result, currentIndex, arrays[i].length);
currentIndex += arrays[i].length;
}
return result;
}
Invocar así:
byte[] a;
byte[] b;
byte[] result = concat(a, b);
También funcionará para concatenar 3, 4, 5 matrices, etc.
Hacerlo de esta manera le brinda la ventaja de un código de matriz rápida que también es muy fácil de leer y mantener.
byte[] result = new byte[a.length + b.length];
// copy a to result
System.arraycopy(a, 0, result, 0, a.length);
// copy b to result
System.arraycopy(b, 0, result, a.length, b.length);
Si prefiere ByteBuffer
como @kalefranz, siempre existe la posibilidad de concatenar dos byte[]
(o incluso más) en una línea, como esta:
byte[] c = ByteBuffer.allocate(a.length+b.length).put(a).put(b).array();
Puede usar bibliotecas de terceros para Clean Code como Apache Commons Lang y usarlo como:
byte[] bytes = ArrayUtils.addAll(a, b);
ArrayUtils.addAll(a, b)
y byte[] c = Bytes.concat(a, b)
, pero este último es más rápido.
Para dos o múltiples matrices, se puede utilizar este método de utilidad simple y limpio:
/**
* Append the given byte arrays to one big array
*
* @param arrays The arrays to append
* @return The complete array containing the appended data
*/
public static final byte[] append(final byte[]... arrays) {
final ByteArrayOutputStream out = new ByteArrayOutputStream();
if (arrays != null) {
for (final byte[] array : arrays) {
if (array != null) {
out.write(array, 0, array.length);
}
}
}
return out.toByteArray();
}
Si está fusionando dos conjuntos de bytes que contienen PDF, esta lógica no funcionará. Necesitamos usar una herramienta de terceros como PDFbox de Apache:
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
mergePdf.addSource(new ByteArrayInputStream(a));
mergePdf.addSource(new ByteArrayInputStream(b));
mergePdf.setDestinationStream(byteArrayOutputStream);
mergePdf.mergeDocuments();
c = byteArrayOutputStream.toByteArray();
Si no desea meterse con los tamaños de las matrices, simplemente use la magia de la concatenación de cadenas:
byte[] c = (new String(a, "l1") + new String(b, "l1")).getBytes("l1");
O defina en algún lugar de su código
// concatenation charset
static final java.nio.charset.Charset cch = java.nio.charset.StandardCharsets.ISO_8859_1;
y use
byte[] c = (new String(a, cch) + new String(b, cch)).getBytes(cch);
Esto, por supuesto, también funciona con más de dos concatenaciones de cadenas usando el +
operador de suma.
Ambos "l1"
e ISO_8859_1
indican el conjunto de caracteres del latín occidental 1 que codifica cada carácter como un solo byte. Como no se realizan traducciones de varios bytes, los caracteres de la cadena tendrán los mismos valores que los bytes (excepto que siempre se interpretarán como valores positivos, ya char
que no están firmados). Al menos para el tiempo de ejecución proporcionado por Oracle, cualquier byte se "decodificará" correctamente y luego "codificará" nuevamente.
Tenga en cuenta que las cadenas expanden la matriz de bytes con consideración, lo que requiere memoria adicional. Las cadenas también pueden ser internadas y, por lo tanto, no serán fáciles de eliminar. Las cadenas también son inmutables, por lo que los valores dentro de ellas no se pueden destruir. Por lo tanto, no debe concatenar matrices sensibles de esta manera ni utilizar este método para matrices de bytes más grandes. También sería necesario dar una indicación clara de lo que está haciendo, ya que este método de concatenación de matrices no es una solución común.
¡Esta es mi forma de hacerlo!
public static byte[] concatByteArrays(byte[]... inputs) {
int i = inputs.length - 1, len = 0;
for (; i >= 0; i--) {
len += inputs[i].length;
}
byte[] r = new byte[len];
for (i = inputs.length - 1; i >= 0; i--) {
System.arraycopy(inputs[i], 0, r, len -= inputs[i].length, inputs[i].length);
}
return r;
}
Caracteristicas :
...
) para ser llamado con cualquier número de byte [].System.arraycopy()
que se implementa con código nativo específico de la máquina, para garantizar un funcionamiento a alta velocidad.int
variables reutilizando las variables i
y len
.Tener en cuenta :
La mejor manera de hacer esto es copiando el código @Jonathan . El problema proviene de las matrices de variables nativas, porque Java crea nuevas variables cuando este tipo de datos se pasa a otra función.
System.arrayCopy
,ByteBuffer
y el - no es tan eficiente, pero legible -ByteArrayOutputStream
todos se han cubierto. Tenemos más de 7 engaños de las respuestas dadas aquí. Por favor, no publique más engaños.