webentwicklung-frage-antwort-db.com.de

Gibt es in Java ein Äquivalent zu memcpy ()?

Ich habe ein Byte [] und möchte es in ein anderes Byte [] kopieren. Vielleicht zeige ich hier meinen einfachen 'C'-Hintergrund, aber gibt es ein Äquivalent zu memcpy () auf Byte-Arrays in Java?

70
simon

Sie könnten versuchen, System.arraycopy oder Array-Funktionen in der Arrays Klasse wie Java.util.Arrays.copyOf zu verwenden. Beide sollten Ihnen native Leistung unter der Haube geben.

Arrays.copyOf ist wahrscheinlich für die Lesbarkeit günstig, wurde jedoch nur in Java 1.6 eingeführt.

 byte[] src = {1, 2, 3, 4};
 byte[] dst = Arrays.copyOf(src, src.length);
 System.out.println(Arrays.toString(dst));
81
Tom

Verwenden Sie System.arraycopy ()

System.arraycopy(sourceArray, 
                 sourceStartIndex,
                 targetArray,
                 targetStartIndex,
                 length);

Beispiel,

String[] source = { "alpha", "beta", "gamma" };
String[] target = new String[source.length];
System.arraycopy(source, 0, target, 0, source.length);


oder verwenden Sie Arrays.copyOf ()
Beispiel,

target = Arrays.copyOf(source, length);

Java.util.Arrays.copyOf(byte[] source, int length) wurde in JDK 1.6 hinzugefügt.

Die copyOf()-Methode verwendet System.arrayCopy() zum Erstellen einer Kopie des Arrays, ist jedoch flexibler als clone(), da Sie Kopien von Teilen eines Arrays erstellen können.

89
Zaki

Wenn Sie nur eine genaue Kopie eines eindimensionalen Arrays wünschen, verwenden Sie clone() .

byte[] array = { 0x0A, 0x01 };
byte[] copy = array.clone();

Für andere Array-Kopiervorgänge verwenden Sie System.arrayCopyArrays.copyOf wie Tom schlägt vor.

_/Im Allgemeinen sollte clone vermieden werden, dies ist jedoch eine Ausnahme von der Regel.

7
McDowell

Sie können System.arrayCopy verwenden. Es kopiert Elemente aus einem Quell-Array in ein Ziel-Array. Die Sun-Implementierung verwendet einen von Hand optimierten Assembler. Dies ist also schnell.

5
mdma

Java hat tatsächlich so etwas wie memcpy (). Die Unsafe-Klasse verfügt über eine copyMemory () -Methode, die im Wesentlichen mit memcpy () identisch ist. Wie memcpy () bietet es natürlich keinen Schutz vor Speicherüberlagerungen, Datenvernichtung usw. Es ist nicht klar, ob es sich wirklich um ein Memcpy () oder ein Memmove () handelt. Es kann verwendet werden, um von tatsächlichen Adressen zu tatsächlichen Adressen oder von Referenzen zu Referenzen zu kopieren. Beachten Sie, dass Sie bei Verwendung von Referenzen einen Offset angeben müssen (andernfalls wird die JVM so schnell wie möglich sein). 

Unsafe.copyMemory () funktioniert (bis zu 2 GB pro Sekunde an meinem alten, müden PC). Benutzung auf eigene Gefahr. Beachten Sie, dass die Unsafe-Klasse nicht für alle JVM-Implementierungen vorhanden ist.

3
Peter Schaeffer

Sie können System.arraycopy verwenden.

2
Artem Barger

No. Java hat keine Entsprechung zu memcpy. Java hat stattdessen ein Äquivalent zu memmove.

Wenn sich die Argumente src und dest auf dasselbe Arrayobjekt beziehen, wird das Kopieren so durchgeführt, als ob die Komponenten an den Positionen srcPos bis srcPos + length-1 zuerst in ein temporäres Array mit Längenkomponenten und dann den Inhalt des temporären Arrays kopiert wurden in Positionen destPos durch destPos + length-1 des Zielarrays kopiert.

Oracle Docs

Es ist sehr wahrscheinlich, dass System.arraycopy niemals dieselbe Leistung wie memcpy hat, wenn src und dest auf dasselbe Array verweisen. Normalerweise ist dies jedoch schnell genug.

Verwenden Sie byteBufferViewVarHandle oder byteArrayViewVarHandle.

Dadurch können Sie ein Array von "Longs" direkt in ein Array von "Doubles" und ähnlichem kopieren.

public long[] toLongs(byte[] buf) {
    int end = buf.length >> 3;
    long[] newArray = new long[end];
    for (int ii = 0; ii < end; ++ii) {
        newArray[ii] = (long)AS_LONGS_VH.get(buf, ALIGN_OFFSET + ii << 3);
    }
}

private static final ALIGN_OFFSET = ByteBuffer.wrap(new byte[0]).alignmentOffset(8); 
private static final VarHandle AS_LONGS_VH = MethodHandles.byteArrayViewVarHandle(long[].class, ByteOrder.nativeOrder());

Dadurch können Sie das Hacken wie folgt durchführen:

float thefloat = 0.4;
int floatBits;
_Static_assert(sizeof theFloat == sizeof floatBits, "this bit twiddling hack requires floats to be equal in size to ints");
memcpy(&floatBits, &thefloat, sizeof floatBits);