Який простий спосіб об'єднати два byte
масиви?
Сказати,
byte a[];
byte b[];
Як з'єднати два byte
масиви і зберегти його в іншому byte
масиві?
Який простий спосіб об'єднати два byte
масиви?
Сказати,
byte a[];
byte b[];
Як з'єднати два byte
масиви і зберегти його в іншому byte
масиві?
Відповіді:
Найелегантніший спосіб зробити це за допомогою a ByteArrayOutputStream
.
byte a[];
byte b[];
ByteArrayOutputStream outputStream = new ByteArrayOutputStream( );
outputStream.write( a );
outputStream.write( b );
byte c[] = outputStream.toByteArray( );
outputStream.write( c );
- вам не доведеться повертатися назад і редагувати рядок, де ви створюєте масив байтів результатів. Крім того, переупорядкувати масиви просто, на відміну від використання методу масиву копіювання.
a.length + b.length
як аргумент для ByteArrayOutputStream
конструктора. Зауважте, що цей метод все одно буде копіювати всі байти в новий масив, який потрібно призначити c[]
! Розглянемо ByteBuffer
метод близького суперника, який не втрачає пам'ять.
Ось приємне рішення за допомогою Guava '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 відповідей. Будь ласка, не публікуйте більше жодної грані.