Простой способ объединить два байтовых массива

Каков простой способ объединения byte массивов?

Сказать,

byte a[];
byte b[];

Как объединить два byte массива и сохранить их в другом byte массиве?

Ответ 1

Самый простой:

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

Ответ 2

Самый элегантный способ сделать это с помощью ByteArrayOutputStream.

byte a[];
byte b[];

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

byte c[] = outputStream.toByteArray( );

Ответ 3

Вот хорошее решение с использованием Guava com.google.common.primitives.Bytes:

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

Самое замечательное в этом методе то, что он имеет подпись varargs:

public static byte[] concat(byte[]... arrays)

Это означает, что вы можете объединить произвольное количество массивов за один вызов метода.

Ответ 4

Другая возможность - использовать java.nio.ByteBuffer.

Что-то вроде

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();

Обратите внимание, что массив должен иметь соответствующий размер, чтобы начать с него, поэтому требуется строка выделения (так как array() просто возвращает базовый массив без учета смещения, положения или предела).

Ответ 5

Другим способом является использование служебной функции (вы можете сделать это статическим методом общего класса утилиты, если хотите):

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;
}

Вызвать так:

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

Он также будет работать для конкатенации 3, 4, 5 массивов и т.д.

Выполнение этого способа дает вам преимущество быстрого кода arraycopy, который также очень легко читать и поддерживать.

Ответ 6

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

Ответ 7

Если вы предпочитаете ByteBuffer как @kalefranz, всегда есть возможность объединить два byte[] (или даже больше) в одну строку, например:

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

Ответ 8

Вы можете использовать сторонние библиотеки для Clean Code, например Apache Commons Lang, и использовать его как:

byte[] bytes = ArrayUtils.addAll(a, b);

Ответ 9

Два вызова System.arraycopy являются скудными и средними, но не легкими на глазах (сложнее понять как рецензент кода, то есть).

Более читаемый подход с использованием java.nio.ByteBuffer:

byte[] ab = ByteBuffer.wrap(new byte[a.length + b.length]).put(a).put(b).array();

Ответ 10

Для двух или нескольких массивов этот простой и чистый метод полезности можно использовать:

/**
 * 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();
}

Ответ 11

Если вы не хотите связываться с размерами массивов, просто используйте магию конкатенации строк:

byte[] c = (new String(a, "l1") + new String(b, "l1")).getBytes("l1");

Или определите где-нибудь в своем коде

// concatenation charset
static final java.nio.charset.Charset cch = java.nio.charset.StandardCharsets.ISO_8859_1;

и использовать

byte[] c = (new String(a, cch) + new String(b, cch)).getBytes(cch);

Это, конечно, также работает с более чем двумя конкатенациями строк с использованием оператора + сложение.


И "l1" и ISO_8859_1 указывают набор символов западной латиницы 1, который кодирует каждый символ в виде одного байта. Поскольку многобайтовые преобразования не выполняются, символы в строке будут иметь те же значения, что и байты (за исключением того, что они всегда будут интерпретироваться как положительные значения, так как char имеет знака). Поэтому, по крайней мере, для предоставляемой Oracle среды выполнения любой байт будет правильно "декодирован", а затем снова "закодирован".

Помните, что строки действительно расширяют байтовый массив, требуя дополнительной памяти. Струны также могут быть интернированы и поэтому не легко удаляются. Строки также неизменны, поэтому значения внутри них не могут быть уничтожены. Поэтому не следует объединять чувствительные массивы таким образом и не следует использовать этот метод для больших байтовых массивов. Также потребуется четкое указание на то, что вы делаете, так как этот метод объединения массивов не является распространенным решением.

Ответ 12

Объединить два массива байтов PDF

Если вы объединяете массивы двух байтов, содержащие PDF, эта логика не будет работать. Нам нужно использовать сторонний инструмент, например PDFbox от Apache:

ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
mergePdf.addSource(new ByteArrayInputStream(a));
mergePdf.addSource(new ByteArrayInputStream(b));
mergePdf.setDestinationStream(byteArrayOutputStream);
mergePdf.mergeDocuments();
c = byteArrayOutputStream.toByteArray();

Ответ 13

Это мой способ сделать это!

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;
}

Особенности:

  • Используйте varargs (...) для вызова с любым числом байтов [].
  • Используйте System.arraycopy() который реализован с машинным родным кодом, чтобы обеспечить высокую скорость работы.
  • Создайте новый байт [] с точным размером, который нужен.
  • Выделите немного меньше переменных типа int, повторно используя переменные i и len.
  • Более быстрое сравнение с константами.

Имейте в виду:

Лучший способ сделать это - скопировать код @Jonathan. Проблема возникает из массивов собственных переменных, потому что Java создает новые переменные, когда этот тип данных передается другой функции.