java.nio.ByteBuffer#duplicate()
Renvoie un nouveau tampon d'octets qui partage le contenu de l'ancien tampon. Les modifications apportées au contenu de l'ancien tampon seront visibles dans le nouveau tampon, et vice versa. Que faire si je veux une copie profonde du tampon d'octets?Copie en profondeur duplicate() de ByteBuffer Java
Répondre
Vous aurez besoin d'itérer toute la mémoire tampon et de la copier par valeur dans le nouveau tampon.
Je pense que la copie profonde ne doit pas impliquer byte[]
. Effectuez les actions suivantes:
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;
}
Pourquoi ai-je besoin de retourner le clone? Ensuite, la limite est inférieure à ma capacité réelle – Karussell
WOW! C'était utile.THanks! –
La seule chose qui n'est pas copiée dans ce cas est la marque, alors sachez que si vous utilisez marque, elle sera perdue. De plus, cette fonction copie seulement du début à la limite et la position de l'original est perdue, je suggérerais de mettre position = 0 et limit = capacité et de les stocker comme temp vars à réinitialiser sur original et cloner avant de revenir. Le rembobinage supprime également la marque, ce qui n'est probablement pas une bonne idée. Je posterai une réponse avec une méthode plus complète. – LINEMAN78
Basé hors de la solution de mingfai:
Cela vous donnera une copie en profondeur presque vrai. La seule chose perdue sera la marque. Si orig est un HeapBuffer et que le décalage n'est pas égal à zéro ou que la capacité est inférieure au tableau de sauvegarde, les données périphériques ne sont pas copiées.
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);
}
}
Cette question est encore comme l'un des premiers coups à la copie d'un ByteBuffer
, je proposerai ma solution. Cette solution ne touche pas le tampon d'origine, y compris les marques définies, et renvoie une copie profonde avec la même capacité que l'original.
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;
}
Si l'on prend soin de la position, limite, ou pour régler le même que l'original, alors c'est un ajout facile au-dessus:
clone.position(original.position());
clone.limit(original.limit());
clone.order(original.order());
return clone;
Pourquoi pas 'clone.put (readOnlyCopy)' au lieu du tableau intermédiaire 'byte'? – seh
@seh Parce que j'étais stupide et n'ai pas vu cette méthode. Merci de l'avoir signalé. – jdmichal
C'est la meilleure solution. Il ne mute pas le contenu original et fournit les moyens les plus propres de faire la même chose. –
Encore une solution simple
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;
}
Il y a une surcharge (optionnelle) de la méthode 'put' qui fait cela pour vous. – nos
Woohoo! J'ai appris quelque chose de nouveau. – Kylar