java.nio.ByteBuffer#duplicate()
gibt einen neuen Byte-Puffer zurück, der den Inhalt des alten Puffers teilt. Änderungen am Inhalt des alten Puffers werden im neuen Puffer angezeigt und umgekehrt. Was ist, wenn ich eine tiefe Kopie des Byte-Puffers möchte?Deep Copy Duplicate() von Javas ByteBuffer
Antwort
Sie müssen den gesamten Puffer durchlaufen und nach Wert in den neuen Puffer kopieren.
Ich denke, die tiefe Kopie muss byte[]
nicht beinhalten. Versuchen Sie Folgendes:
public static ByteBuffer clone(ByteBuffer original) {
ByteBuffer clone = ByteBuffer.allocate(original.capacity());
original.rewind();//copy from the beginning
clone.put(original);
original.rewind();
clone.flip();
return clone;
}
Warum muss ich den Klon umdrehen? Dann ist das Limit niedriger als meine tatsächliche Kapazität – Karussell
WOW! Das war hilfreich.THanks! –
Die einzige Sache, die in diesem Fall nicht kopiert wird, ist die Markierung, also wissen Sie einfach, dass, wenn Sie Markierung benutzen, es verloren ist. Außerdem kopiert diese Funktion nur vom Anfang bis zum Limit und die Position des Originals ist verloren. Ich würde vorschlagen, position = 0 und limit = capacity zu setzen und sie als temp vars zu speichern, um sie auf Original und Klon zurückzusetzen, bevor sie zurückkehren. Auch Rückspulen verwirft das Zeichen, also ist das wahrscheinlich keine gute Idee. Ich werde eine Antwort mit einer vollständigeren Methode veröffentlichen. – LINEMAN78
Basierend off Lösung von mingfai suchen:
Dies gibt Ihnen eine fast wahre tiefe Kopie. Das einzige, was verloren geht, ist die Marke. Wenn orig ein HeapBuffer ist und der Offset nicht Null ist oder die Kapazität kleiner ist als das Hintergrundarray, werden die außerhalb liegenden Daten nicht kopiert.
public static ByteBuffer deepCopy(ByteBuffer orig)
{
int pos = orig.position(), lim = orig.limit();
try
{
orig.position(0).limit(orig.capacity()); // set range to entire buffer
ByteBuffer toReturn = deepCopyVisible(orig); // deep copy range
toReturn.position(pos).limit(lim); // set range to original
return toReturn;
}
finally // do in finally in case something goes wrong we don't bork the orig
{
orig.position(pos).limit(lim); // restore original
}
}
public static ByteBuffer deepCopyVisible(ByteBuffer orig)
{
int pos = orig.position();
try
{
ByteBuffer toReturn;
// try to maintain implementation to keep performance
if(orig.isDirect())
toReturn = ByteBuffer.allocateDirect(orig.remaining());
else
toReturn = ByteBuffer.allocate(orig.remaining());
toReturn.put(orig);
toReturn.order(orig.order());
return (ByteBuffer) toReturn.position(0);
}
finally
{
orig.position(pos);
}
}
Da diese Frage immer noch kommt als einer der ersten Hits zu einem ByteBuffer
Kopieren, werde ich meine Lösung. Diese Lösung berührt nicht den ursprünglichen Puffer, einschließlich Markensätze, und gibt eine tiefe Kopie mit derselben Kapazität wie das Original zurück.
public static ByteBuffer cloneByteBuffer(final ByteBuffer original) {
// Create clone with same capacity as original.
final ByteBuffer clone = (original.isDirect()) ?
ByteBuffer.allocateDirect(original.capacity()) :
ByteBuffer.allocate(original.capacity());
// Create a read-only copy of the original.
// This allows reading from the original without modifying it.
final ByteBuffer readOnlyCopy = original.asReadOnlyBuffer();
// Flip and read from the original.
readOnlyCopy.flip();
clone.put(readOnlyCopy);
return clone;
}
Wenn man sich für die Position, die Grenze kümmert, oder um das gleiche wie das Original eingestellt werden, dann ist das eine einfache Ergänzung zu der oben:
clone.position(original.position());
clone.limit(original.limit());
clone.order(original.order());
return clone;
Warum nicht 'clone.put (readOnlyCopy)' anstelle des mittleren 'Byte'-Arrays? – seh
@Seh Weil ich dumm war und diese Methode nicht sah. Danke, dass du es aufgezeigt hast. – jdmichal
Dies ist die beste Lösung. Es mutiert nicht den ursprünglichen Inhalt und bietet die saubersten Möglichkeiten, dasselbe zu tun. –
Eine einfachere Lösung
public ByteBuffer deepCopy(ByteBuffer source, ByteBuffer target) {
int sourceP = source.position();
int sourceL = source.limit();
if (null == target) {
target = ByteBuffer.allocate(source.remaining());
}
target.put(source);
target.flip();
source.position(sourceP);
source.limit(sourceL);
return target;
}
Es gibt eine (optionale) Überladung der 'put' Methode, die das für Sie tut. – nos
Woohoo! Ich habe etwas Neues gelernt. – Kylar