Quelle est la méthode la plus simple pour concaténer deux byte
tableaux?
Dire,
byte a[];
byte b[];
Comment concaténer deux byte
baies et les stocker dans une autre byte
baie?
Quelle est la méthode la plus simple pour concaténer deux byte
tableaux?
Dire,
byte a[];
byte b[];
Comment concaténer deux byte
baies et les stocker dans une autre byte
baie?
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.length
comme argument pour le ByteArrayOutputStream
constructeur. Notez que cette méthode copiera toujours tous les octets dans un nouveau tableau auquel les affecter c[]
! Considérez la ByteBuffer
mé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.HeapByteBuffer
sous-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.
allocate
mé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ù ByteBuffer
est 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 ByteBuffer
comme @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_1
indiquent 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 char
non 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.int
variables en réutilisant les variables i
et 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
,ByteBuffer
et - pas efficace mais lisible -ByteArrayOutputStream
ont tous été couverts. Nous avons plus de 7 dupes des réponses données ici. Merci de ne plus poster de dupes.