Quelle est la méthode la plus simple pour concaténer deux bytetableaux?
Dire,
byte a[];
byte b[];
Comment concaténer deux bytebaies et les stocker dans une autre bytebaie?
Quelle est la méthode la plus simple pour concaténer deux bytetableaux?
Dire,
byte a[];
byte b[];
Comment concaténer deux bytebaies et les stocker dans une autre bytebaie?
Réponses:
La façon la plus élégante de le faire est d'utiliser a ByteArrayOutputStream.
byte a[];
byte b[];
ByteArrayOutputStream outputStream = new ByteArrayOutputStream( );
outputStream.write( a );
outputStream.write( b );
byte c[] = outputStream.toByteArray( );
outputStream.write( c );- vous n'avez pas besoin de revenir en arrière et de modifier la ligne où vous créez le tableau d'octets de résultat. De plus, la réorganisation des tableaux est simple, contrairement à l'utilisation de la méthode arraycopy.
a.length + b.lengthcomme argument pour le ByteArrayOutputStreamconstructeur. Notez que cette méthode copiera toujours tous les octets dans un nouveau tableau auquel les affecter c[]! Considérez la ByteBufferméthode comme un concurrent proche, qui ne perd pas de mémoire.
Voici une solution agréable en utilisant goyave de com.google.common.primitives.Bytes:
byte[] c = Bytes.concat(a, b);
La grande chose à propos de cette méthode est qu'elle a une signature varargs:
public static byte[] concat(byte[]... arrays)
ce qui signifie que vous pouvez concaténer un nombre arbitraire de tableaux dans un seul appel de méthode.
Une autre possibilité utilise java.nio.ByteBuffer.
Quelque chose comme
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();
Notez que le tableau doit être correctement dimensionné pour commencer, de sorte que la ligne d'allocation est requise (comme array()renvoie simplement le tableau de support, sans tenir compte du décalage, de la position ou de la limite).
ByteBuffer.allocate(int)est une méthode statique qui renvoie une java.nio.HeapByteBuffersous-classe instanciée de ByteBuffer. Les méthodes .put()et .compact()- et tout autre caractère abstrait - sont prises en charge.
compact()Ligne supprimée car elle est incorrecte.
bb.flip(); bb.get(result);à la place de la byte[] result = bb.array();ligne.
allocateméthode révèle ce qui suit: "La position du nouveau tampon sera zéro, sa limite sera sa capacité, sa marque sera indéfinie et chacun de ses éléments sera initialisé à zéro . Il aura un tableau de support et son décalage de tableau sera nul. " Donc , pour ce particulier morceau de code, où ByteBufferest affecté en interne, ce n'est pas un problème.
Une autre façon est d'utiliser une fonction utilitaire (vous pouvez en faire une méthode statique d'une classe utilitaire générique si vous le souhaitez):
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;
}
Invoquez ainsi:
byte[] a;
byte[] b;
byte[] result = concat(a, b);
Il fonctionnera également pour concaténer 3, 4, 5 tableaux, etc.
Le faire de cette façon vous donne l'avantage d'un code de tableau rapide qui est également très facile à lire et à entretenir.
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 vous préférez ByteBuffercomme @kalefranz, il y a toujours la possibilité de concaténer deux byte[](voire plus) sur une même ligne, comme ceci:
byte[] c = ByteBuffer.allocate(a.length+b.length).put(a).put(b).array();
Vous pouvez utiliser des bibliothèques tierces pour Clean Code comme Apache Commons Lang et l'utiliser comme:
byte[] bytes = ArrayUtils.addAll(a, b);
ArrayUtils.addAll(a, b)et byte[] c = Bytes.concat(a, b), mais ce dernier est plus rapide.
Pour deux ou plusieurs tableaux, cette méthode utilitaire simple et propre peut être utilisée:
/**
* 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 vous fusionnez deux tableaux d'octets contenant du PDF, cette logique ne fonctionnera pas. Nous devons utiliser un outil tiers comme PDFbox d'Apache:
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
mergePdf.addSource(new ByteArrayInputStream(a));
mergePdf.addSource(new ByteArrayInputStream(b));
mergePdf.setDestinationStream(byteArrayOutputStream);
mergePdf.mergeDocuments();
c = byteArrayOutputStream.toByteArray();
Si vous ne voulez pas jouer avec la taille des tableaux, utilisez simplement la magie de la concaténation de chaînes:
byte[] c = (new String(a, "l1") + new String(b, "l1")).getBytes("l1");
Ou définissez quelque part dans votre code
// concatenation charset
static final java.nio.charset.Charset cch = java.nio.charset.StandardCharsets.ISO_8859_1;
et utilise
byte[] c = (new String(a, cch) + new String(b, cch)).getBytes(cch);
Bien entendu, cela fonctionne également avec plus de deux concaténations de chaînes à l'aide de l' +opérateur d'addition.
Les deux "l1"et ISO_8859_1indiquent le jeu de caractères Latin occidental 1 qui code chaque caractère sous la forme d'un octet unique. Comme aucune traduction multi-octets n'est effectuée, les caractères de la chaîne auront les mêmes valeurs que les octets (sauf qu'ils seront toujours interprétés comme des valeurs positives, car charnon signés). Au moins pour le runtime fourni par Oracle, tout octet sera donc correctement «décodé» puis «encodé» à nouveau.
Attention, les chaînes étendent considérablement le tableau d'octets, nécessitant de la mémoire supplémentaire. Les cordes peuvent également être internées et ne seront donc pas faciles à retirer. Les chaînes sont également immuables, de sorte que les valeurs qu'elles contiennent ne peuvent pas être détruites. Vous ne devez donc pas concaténer des tableaux sensibles de cette façon, ni utiliser cette méthode pour des tableaux d'octets plus grands. Il serait également nécessaire de donner une indication claire de ce que vous faites, car cette méthode de concaténation de tableau n'est pas une solution courante.
C'est ma façon de le faire!
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;
}
Caractéristiques :
...) pour être appelé avec n'importe quel nombre d'octets [].System.arraycopy()implémentée avec du code natif spécifique à la machine, pour garantir un fonctionnement à grande vitesse.intvariables en réutilisant les variables iet len.Gardez à l'esprit :
La meilleure façon de le faire est de copier le code @Jonathan . Le problème vient des tableaux de variables natifs, car Java crée de nouvelles variables lorsque ce type de données est transmis à une autre fonction.
System.arrayCopy,ByteBufferet - pas efficace mais lisible -ByteArrayOutputStreamont tous été couverts. Nous avons plus de 7 dupes des réponses données ici. Merci de ne plus poster de dupes.