2009-02-20 9 views
5

Qual è il modo più efficiente di inserire il maggior numero possibile di byte da un ByteBuffer bbuf_dest in un altro ByteBuffer (nonché sapere quanti byte sono stati trasferiti)? Sto cercando bbuf_dest.put(bbuf_src) ma sembra voler lanciare BufferOverflowException e non riesco a ottenere i javadoc da Sun adesso (problemi di rete) quando ne ho bisogno. > :(arghtrasferimento di byte da un ByteBuffer a un altro


edit:. Darnit, @ di Richard approccio (uso put() dalla matrice di supporto bbuf_src) non funzionerà se bbuf_src è un buffer ReadOnly, come non è possibile ottenere l'accesso ai tale matrice. Cosa posso fare in questo caso ???

+0

Penso che dovresti suddividere questo in due domande. – GEOCHET

+0

qui l'altra metà è stata trasferita qui: http://stackoverflow.com/questions/570218/downloading-sun-javadocs-mirror-websites –

risposta

1

OK, ho adattato @ risposta di Richard:

public static int transferAsMuchAsPossible(
        ByteBuffer bbuf_dest, ByteBuffer bbuf_src) 
{ 
    int nTransfer = Math.min(bbuf_dest.remaining(), bbuf_src.remaining()); 
    if (nTransfer > 0) 
    { 
    bbuf_dest.put(bbuf_src.array(), 
        bbuf_src.arrayOffset()+bbuf_src.position(), 
        nTransfer); 
    bbuf_src.position(bbuf_src.position()+nTransfer); 
    } 
    return nTransfer; 
} 

e un test per assicurarsi che funzioni:

public static boolean transferTest() 
{ 
    ByteBuffer bb1 = ByteBuffer.allocate(256); 
    ByteBuffer bb2 = ByteBuffer.allocate(50); 
    for (int i = 0; i < 100; ++i) 
    { 
     bb1.put((byte)i); 
    } 
    bb1.flip(); 
    bb1.position(5); 
    ByteBuffer bb1a = bb1.slice(); 
    bb1a.position(2); 
    // bb3 includes the 5-100 range 
    bb2.put((byte)77); 
    // something to see this works when bb2 isn't empty 
    int n = transferAsMuchAsPossible(bb2, bb1a); 
    boolean itWorked = (n == 49); 

    if (bb1a.position() != 51) 
     itWorked = false; 
    if (bb2.position() != 50) 
     itWorked = false; 
    bb2.rewind(); 
    if (bb2.get() != 77) 
     itWorked = false; 
    for (int i = 0; i < 49; ++i) 
    { 
     if (bb2.get() != i+7) 
     { 
      itWorked = false; 
      break; 
     } 
    } 
    return itWorked; 
} 
1

si ottiene il BufferOverflowException perché il bbuf_dest non è abbastanza grande.

sarà necessario utilizzare bbuf_dest.remaining() per scoprire il numero massimo di byte che puoi trasferire da bbuf_src:

int maxTransfer = Math.min(bbuf_dest.remaining(), bbuf_src.remaining()); 
bbuf_dest.put(bbuf_src.array(), 0, maxTransfer); 
+0

Ah. Questo è utile. Penso di sapere cosa fare ora. Grazie. Ma nota che la tua risposta non funzionerà se bbuf_src è un buffer di visualizzazione per un altro buffer. Penso di potermi adattare però. –

+0

(o se la posizione di bbuf_src è> 0) –

+0

... e devo anche aggiornare la posizione di bbuf_src. –

8

Come hai scoperto, ottenendo la matrice supporto non sempre lavoro (non riesce a buffer di sola lettura, buffer diretti e buffer di file mappati in memoria). L'alternativa migliore consiste nel duplicare il buffer di origine e impostare un nuovo limite per la quantità di dati che si desidera trasferire:

int maxTransfer = Math.min(bbuf_dest.remaining(), bbuf_src.remaining()); 
// use a duplicated buffer so we don't disrupt the limit of the original buffer 
ByteBuffer bbuf_tmp = bbuf_src.duplicate(); 
bbuf_tmp.limit (bbuf_tmp.position() + maxTransfer); 
bbuf_dest.put (bbuf_tmp); 

// now discard the data we've copied from the original source (optional) 
bbuf_src.position(bbuf_src.position() + maxTransfer); 
+0

Ma Oracle dice che il limite deve essere "non più grande della capacità del buffer". La duplicazione di un buffer duplicherà la sua capacità, non è vero? –