web-dev-qa-db-fra.com

Un moyen facile de concaténer des tableaux de deux octets

Quel est le moyen facile de concaténer deux tableaux byte?

Dire,

byte a[];
byte b[];

Comment concaténer deux tableaux byte et les stocker dans un autre tableau byte?

228
androidGuy

Le plus simple:

byte[] c = new byte[a.length + b.length];
System.arraycopy(a, 0, c, 0, a.length);
System.arraycopy(b, 0, c, a.length, b.length);
296
Jonathan

La manière la plus élégante de faire cela est avec un ByteArrayOutputStream.

byte a[];
byte b[];

ByteArrayOutputStream outputStream = new ByteArrayOutputStream( );
outputStream.write( a );
outputStream.write( b );

byte c[] = outputStream.toByteArray( );
340
Kevin

Voici une solution intéressante utilisant com.google.common.primitives.Bytes de Guava :

byte[] c = Bytes.concat(a, b);

Le grand avantage 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.

62
Zoltán

Une autre possibilité consiste à utiliser 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'attribution est requise (car array() renvoie simplement le tableau de sauvegarde, sans prendre en compte le décalage, la position ou la limite).

27
kalefranz

Une autre méthode consiste à utiliser une fonction d’utilité (vous pouvez en faire une méthode statique d’une classe d’utilité 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;
}

Invoquer comme ça:

byte[] a;
byte[] b;
byte[] result = concat(a, b);

Cela fonctionnera également pour concaténer 3, 4, 5 tableaux, etc.

En procédant ainsi, vous bénéficiez d'un code arraycopy rapide, très facile à lire et à gérer.

13
Wayne Uroda

Vous pouvez utiliser des bibliothèques tierces pour Clean Code comme Apache Commons Lang et les utiliser comme suit:

byte[] bytes = ArrayUtils.addAll(a, b);
10
Tomasz Przybylski
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);
10
James.Xu

Si vous préférez ByteBuffer comme @kalefranz, vous avez toujours la possibilité de concaténer deux byte[] (ou même plus) en une seule ligne, comme ceci:

byte[] c = ByteBuffer.allocate(a.length+b.length).put(a).put(b).array();
9
ZEuS

Pour deux ou plusieurs baies, cette méthode d’utilité 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();
}
5
Jeroen Meulemeester

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éfinir 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);

Ceci, bien sûr, fonctionne également avec plus de deux concaténations de chaînes utilisant l'opérateur d'addition +.


"l1" et ISO_8859_1 indiquent tous deux le jeu de caractères occidental latin 1 codant chaque caractère sous forme d'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 n'est pas signé). Au moins pour l'exécution fournie par Oracle, tout octet sera donc correctement "décodé" puis "codé" à nouveau.

Attention, les chaînes développent le tableau d'octets avec précaution, nécessitant de la mémoire supplémentaire. Les chaînes peuvent également être internées et ne seront donc pas facilement supprimées. Les chaînes étant également immuables, les valeurs qu’elles contiennent ne peuvent pas être détruites. Par conséquent, vous ne devez pas concaténer les tableaux sensibles de cette manière, ni utiliser cette méthode pour les tableaux d'octets plus volumineux. Il serait également nécessaire d'indiquer clairement ce que vous faites, car cette méthode de concaténation de tableaux n'est pas une solution courante.

1
John McClane

Fusionner deux tableaux PDF

Si vous fusionnez des tableaux de deux octets contenant un fichier PDF, cette logique ne fonctionnera pas. Nous devons utiliser un outil tiers tel que 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();
1
Bala Vignesh B

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 :

  • Utilisez varargs (...) pour être appelé avec un nombre quelconque d'octets [].
  • Utilisez System.arraycopy() qui est implémenté avec un code natif spécifique à la machine pour garantir un fonctionnement à grande vitesse.
  • Créez un nouvel octet [] avec la taille exacte requise.
  • Allouez un peu moins de variables int en réutilisant les variables i et len.
  • Comparaison plus rapide avec les constantes.

Gardez à l'esprit :

Le meilleur moyen de le faire est de copier le @ code Jonathan . Le problème provient des tableaux de variables natives, car Java crée de nouvelles variables lorsque ce type de données est transmis à une autre fonction.

0
Daniel De León