Каков простой способ объединения двух byte
массивов?
Сказать,
byte a[];
byte b[];
Как объединить два byte
массива и сохранить его в другом byte
массиве?
Каков простой способ объединения двух byte
массивов?
Сказать,
byte a[];
byte b[];
Как объединить два byte
массива и сохранить его в другом byte
массиве?
Ответы:
Самый элегантный способ сделать это с ByteArrayOutputStream
.
byte a[];
byte b[];
ByteArrayOutputStream outputStream = new ByteArrayOutputStream( );
outputStream.write( a );
outputStream.write( b );
byte c[] = outputStream.toByteArray( );
outputStream.write( c );
- вам не нужно возвращаться и редактировать строку, где вы создаете результирующий байтовый массив. Кроме того, переупорядочение массивов просто, в отличие от использования метода arraycopy.
a.length + b.length
качестве аргумента для ByteArrayOutputStream
конструктора. Обратите внимание, что этот метод все равно будет копировать все байты в новый массив для назначения c[]
! Рассмотрим ByteBuffer
метод близкого соперника, который не тратит память.
Вот хорошее решение с использованием гуавы «s com.google.common.primitives.Bytes
:
byte[] c = Bytes.concat(a, b);
Самое замечательное в этом методе то, что он имеет подпись varargs:
public static byte[] concat(byte[]... arrays)
Это означает, что вы можете объединить произвольное количество массивов за один вызов метода.
Другая возможность использования 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()
просто возвращается вспомогательный массив, без учета смещения, положения или предела).
ByteBuffer.allocate(int)
является статическим методом, который возвращает экземпляр java.nio.HeapByteBuffer
класса ByteBuffer
. .put()
И .compact()
методы - и любые другие абстрактно-Несс - позаботятся.
compact()
строка, так как она неверна.
bb.flip(); bb.get(result);
вместо byte[] result = bb.array();
линии.
allocate
метода показывает следующее: «Позиция нового буфера будет нулевой, его предел будет его емкостью, его метка будет неопределенной, а каждый из его элементов будет инициализирован нулем. У него будет резервный массив, а смещение его массива будет равно нулю. " Так что для этого конкретного фрагмента кода, где ByteBuffer
он размещен внутри, это не проблема.
Другой способ - использовать служебную функцию (вы можете сделать это статическим методом универсального служебного класса, если хотите):
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 массивов и т. Д.
Делая это таким образом, вы получаете преимущество быстрого кода копирования массива, который также очень легко читать и поддерживать.
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);
Если вы предпочитаете ByteBuffer
как @kalefranz, всегда есть возможность объединить два byte[]
(или даже больше) в одну строку, например так:
byte[] c = ByteBuffer.allocate(a.length+b.length).put(a).put(b).array();
Вы можете использовать сторонние библиотеки для чистого кода, такие как Apache Commons Lang, и использовать их следующим образом:
byte[] bytes = ArrayUtils.addAll(a, b);
ArrayUtils.addAll(a, b)
и byte[] c = Bytes.concat(a, b)
, но последний быстрее.
Для двух или нескольких массивов можно использовать этот простой и чистый служебный метод:
/**
* 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();
}
Если вы объединяете два байтовых массива, которые содержат 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();
Если вы не хотите связываться с размерами массивов, просто используйте магию конкатенации строк:
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 среды выполнения любой байт будет правильно «декодирован», а затем снова «закодирован».
Помните, что строки действительно расширяют байтовый массив, требуя дополнительной памяти. Струны также могут быть интернированы и поэтому не легко удаляются. Строки также являются неизменяемыми, поэтому значения внутри них не могут быть уничтожены. Поэтому не следует объединять чувствительные массивы таким образом и не следует использовать этот метод для больших байтовых массивов. Также потребуется четкое указание на то, что вы делаете, так как этот метод объединения массивов не является распространенным решением.
Это мой способ сделать это!
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;
}
Особенности :
...
) для вызова с любым числом байтов [].System.arraycopy()
это реализовано с машинным родным кодом, чтобы обеспечить высокую скорость работы.int
переменных за счет повторного использования i
и len
переменные.Имейте в виду :
Лучший способ сделать это - скопировать код @Jonathan . Проблема связана с массивами собственных переменных, потому что Java создает новые переменные, когда этот тип данных передается другой функции.
System.arrayCopy
,ByteBuffer
и тому - не так эффективно , но читаемым -ByteArrayOutputStream
все были охвачены. У нас есть более 7 вариантов ответов, приведенных здесь. Пожалуйста, не размещайте больше дупов.