java.nio.ByteBuffer#duplicate()
zwraca nowy bufor bajtowy, który udostępnia zawartość starego bufora. Zmiany w zawartości starego bufora będą widoczne w nowym buforze i na odwrót. Co się stanie, jeśli chcę mieć głęboką kopię bufora bajtowego?Duplikat kopii głębokiej() Javy ByteBuffer
Odpowiedz
Będziesz musiał powtórzyć cały bufor i skopiować według wartości do nowego bufora.
Myślę, że kopia nie musi zawierać byte[]
. Spróbuj wykonać następujące czynności:
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;
}
Dlaczego muszę odwrócić klon? Wtedy limit jest niższy niż moja prawdziwa pojemność – Karussell
WOW! To było pomocne. Dzięki! –
Jedyną rzeczą, która nie została skopiowana w tym przypadku, jest znak, więc po prostu wiedz, że jeśli użyjesz znaku, zostanie utracone. Ponadto ta funkcja kopiuje tylko od początku do limitu, a pozycja oryginału jest tracona, sugerowałbym ustawienie position = 0 i limit = capacity i przechowywanie ich jako zmiennych tymczasowych, które mają być zresetowane na oryginale i sklonowane przed powrotem. Również przewijanie odrzuca znak, więc użycie tego prawdopodobnie nie jest dobrym pomysłem. Opublikuję odpowiedź bardziej kompletną metodą. – LINEMAN78
oparciu off roztworu mingfai za:
To daje prawie prawdziwą głęboką kopię. Jedyną rzeczą utraconą będzie znak. Jeśli orig jest HeapBuffer, a offset nie jest równy zeru lub pojemność jest mniejsza niż tablica backingowa, niż nie są kopiowane odległe dane.
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);
}
}
Ponieważ kwestia ta nadal pojawia się jako jeden z pierwszych hitów do kopiowania ByteBuffer
, złożę moje rozwiązanie. To rozwiązanie nie dotyka oryginalnego bufora, w tym żadnego zestawu znaczników, i zwróci głęboką kopię o takiej samej pojemności, jak oryginał.
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;
}
Jeśli dba o położeniu, ogranicza, lub aby być ustawione tak samo, jak w oryginale, to jest to łatwe, oprócz wyżej wymienionych:
clone.position(original.position());
clone.limit(original.limit());
clone.order(original.order());
return clone;
Dlaczego nie 'clone.put (readOnlyCopy)' zamiast pośredniej tablicy 'byte'? – seh
@seh Ponieważ byłem głupi i nie widziałem tej metody. Dziękuję za wskazanie. – jdmichal
To jest najlepsze rozwiązanie. Nie modyfikuje oryginalnej zawartości i zapewnia najczystsze sposoby robienia tego samego. –
jedno proste rozwiązanie
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;
}
Istnieje (opcjonalne) przeciążenie metody 'put', która robi to za Ciebie. – nos
Woohoo! Nauczyłem się czegoś nowego. – Kylar