Was ist der einfache Weg, um zwei byte
Arrays zu verketten ?
Sagen,
byte a[];
byte b[];
Wie verkette ich zwei byte
Arrays und speichere sie in einem anderen byte
Array?
Was ist der einfache Weg, um zwei byte
Arrays zu verketten ?
Sagen,
byte a[];
byte b[];
Wie verkette ich zwei byte
Arrays und speichere sie in einem anderen byte
Array?
Antworten:
Der eleganteste Weg, dies zu tun, ist mit einem ByteArrayOutputStream
.
byte a[];
byte b[];
ByteArrayOutputStream outputStream = new ByteArrayOutputStream( );
outputStream.write( a );
outputStream.write( b );
byte c[] = outputStream.toByteArray( );
outputStream.write( c );
- Sie müssen nicht zurückgehen und die Zeile bearbeiten, in der Sie das Ergebnisbyte-Array erstellen. Außerdem ist die Neuanordnung der Arrays im Gegensatz zur Arraycopy-Methode einfach.
a.length + b.length
als Argument für den ByteArrayOutputStream
Konstruktor verwenden. Beachten Sie, dass diese Methode weiterhin alle Bytes in ein neues Array kopiert, dem sie zugewiesen werden soll c[]
! Betrachten Sie die ByteBuffer
Methode als einen engen Konkurrenten, der keinen Speicher verschwendet.
Hier ist eine schöne Lösung mit Guava ‚s com.google.common.primitives.Bytes
:
byte[] c = Bytes.concat(a, b);
Das Tolle an dieser Methode ist, dass sie eine varargs-Signatur hat:
public static byte[] concat(byte[]... arrays)
Dies bedeutet, dass Sie eine beliebige Anzahl von Arrays in einem einzigen Methodenaufruf verketten können.
Eine andere Möglichkeit ist die Verwendung java.nio.ByteBuffer
.
Etwas wie
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();
Beachten Sie, dass das Array zunächst eine angemessene Größe haben muss, sodass die Zuordnungszeile erforderlich ist (da array()
das Backing-Array einfach zurückgegeben wird, ohne den Versatz, die Position oder das Limit zu berücksichtigen).
ByteBuffer.allocate(int)
ist eine statische Methode, die eine instanziierte java.nio.HeapByteBuffer
Unterklasse von zurückgibt ByteBuffer
. Für die .put()
und .compact()
Methoden - und jede andere Abstraktheit - wird gesorgt.
compact()
Zeile entfernt , da sie falsch ist.
bb.flip(); bb.get(result);
anstelle der byte[] result = bb.array();
Zeile ausstelle .
allocate
zeigt das sorgfältige Lesen der Methode Folgendes: "Die Position des neuen Puffers ist Null, seine Grenze ist seine Kapazität, seine Markierung ist undefiniert und jedes seiner Elemente wird auf Null initialisiert Es wird ein Hintergrundarray haben und sein Array-Offset wird Null sein. " Für diesen speziellen Code, bei dem der Code ByteBuffer
intern zugewiesen wird, ist dies kein Problem.
Eine andere Möglichkeit ist die Verwendung einer Dienstprogrammfunktion (Sie können dies zu einer statischen Methode einer generischen Dienstprogrammklasse machen, wenn Sie möchten):
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;
}
Rufen Sie so auf:
byte[] a;
byte[] b;
byte[] result = concat(a, b);
Es funktioniert auch zum Verketten von 3, 4, 5 Arrays usw.
Auf diese Weise erhalten Sie den Vorteil eines schnellen Arraycopy-Codes, der auch sehr einfach zu lesen und zu warten ist.
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);
Wenn Sie ByteBuffer
@kalefranz bevorzugen , besteht immer die Möglichkeit, zwei byte[]
(oder sogar mehr) in einer Zeile wie folgt zu verketten :
byte[] c = ByteBuffer.allocate(a.length+b.length).put(a).put(b).array();
Sie können Bibliotheken von Drittanbietern für Clean Code wie Apache Commons Lang verwenden und wie folgt verwenden:
byte[] bytes = ArrayUtils.addAll(a, b);
ArrayUtils.addAll(a, b)
und byte[] c = Bytes.concat(a, b)
, aber letzteres ist schneller.
Für zwei oder mehrere Arrays kann diese einfache und saubere Dienstprogrammmethode verwendet werden:
/**
* 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();
}
Wenn Sie zwei Byte-Arrays zusammenführen, die PDF enthalten, funktioniert diese Logik nicht. Wir müssen ein Drittanbieter-Tool wie PDFbox von Apache verwenden:
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
mergePdf.addSource(new ByteArrayInputStream(a));
mergePdf.addSource(new ByteArrayInputStream(b));
mergePdf.setDestinationStream(byteArrayOutputStream);
mergePdf.mergeDocuments();
c = byteArrayOutputStream.toByteArray();
Wenn Sie sich nicht mit den Größen von Arrays herumschlagen möchten, verwenden Sie einfach die Magie der Zeichenfolgenverkettung:
byte[] c = (new String(a, "l1") + new String(b, "l1")).getBytes("l1");
Oder definieren Sie irgendwo in Ihrem Code
// concatenation charset
static final java.nio.charset.Charset cch = java.nio.charset.StandardCharsets.ISO_8859_1;
und verwenden
byte[] c = (new String(a, cch) + new String(b, cch)).getBytes(cch);
Dies funktioniert natürlich auch mit mehr als zwei Zeichenfolgenverkettungen unter Verwendung des +
Additionsoperators.
Beide "l1"
und ISO_8859_1
geben den Western Latin 1-Zeichensatz an, der jedes Zeichen als einzelnes Byte codiert. Da keine Mehrbyte-Übersetzungen ausgeführt werden, haben die Zeichen in der Zeichenfolge dieselben Werte wie die Bytes (außer dass sie immer als positive Werte interpretiert werden, alschar
nicht signiert sind). Zumindest für die von Oracle bereitgestellte Laufzeit wird daher jedes Byte korrekt "decodiert" und dann erneut "codiert".
Beachten Sie, dass Zeichenfolgen das Byte-Array erheblich erweitern und zusätzlichen Speicher benötigen. Saiten können auch interniert werden und lassen sich daher nicht leicht entfernen. Zeichenfolgen sind ebenfalls unveränderlich, sodass die darin enthaltenen Werte nicht zerstört werden können. Sie sollten daher vertrauliche Arrays nicht auf diese Weise verketten oder diese Methode für Arrays mit größeren Bytes verwenden. Es wäre auch erforderlich, einen klaren Hinweis darauf zu geben, was Sie tun, da diese Methode der Array-Verkettung keine übliche Lösung ist.
Das ist mein Weg, es zu tun!
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;
}
Eigenschaften :
...
), um mit einer beliebigen Anzahl von Bytes [] aufgerufen zu werden.System.arraycopy()
diese Option mit maschinenspezifischem nativem Code, um einen Hochgeschwindigkeitsbetrieb sicherzustellen.int
Variablen zu, indem Sie die Variablen i
und wiederverwenden len
.Denken Sie daran :
Der bessere Weg, dies zu tun, ist das Kopieren des @ Jonathan-Codes . Das Problem tritt bei den nativen Variablenarrays auf, da Java neue Variablen erstellt, wenn dieser Datentyp an eine andere Funktion übergeben wird.
System.arrayCopy
,ByteBuffer
und die - nicht so effizient , aber lesbar -ByteArrayOutputStream
haben alle abgedeckt. Wir haben mehr als 7 Dupes der hier gegebenen Antworten. Bitte poste keine Dupes mehr.