2009-02-20 13 views
5

Jaki jest najbardziej efektywny sposób na umieszczenie jak największej liczby bajtów z ByteBuffer'a bbuf_src na innym ByteBuffer bbuf_dest (jak również na ile bajtów zostało przesłanych)? Próbuję bbuf_dest.put(bbuf_src), ale wydaje się, że chcesz rzucić wyjątek BufferOverflowException i nie mogę uzyskać javadocs od Sun teraz (problemy z siecią), kiedy ich potrzebuję. > :(arghprzenoszenie bajtów z jednego ByteBuffer na inny


edit:. Darnit @ Richarda podejście (wykorzystanie put() z tablicy poparciem bbuf_src) nie będzie działać, jeśli bbuf_src jest tylko do odczytu bufora, ponieważ nie można uzyskać dostępu do że tablica. Co mogę zrobić w tym przypadku ???

+0

Myślę, że należy podzielić to na dwa pytania. – GEOCHET

+0

druga połowa została przeniesiona tutaj: http://stackoverflow.com/questions/570218/downloading-sun-javadocs-mirror-websites –

Odpowiedz

1

OK, ja dostosowany @ odpowiedź Richarda:

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; 
} 

i badania, aby upewnić się, że działa:

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

Otrzymasz BufferOverflowException ponieważ bbuf_dest nie jest wystarczająco duża.

trzeba będzie użyć bbuf_dest.remaining(), aby dowiedzieć się maksymalną liczbę bajty można przesłać z bbuf_src:

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

Ah. To jest pomocne. Chyba wiem, co mam teraz zrobić. Dzięki. Zauważ, że twoja odpowiedź nie zadziała, jeśli bbuf_src jest buforem widoku dla innego bufora. Myślę, że potrafię to jednak dostosować. –

+0

(lub jeśli pozycja bbuf_src jest> 0) –

+0

... i muszę również zaktualizować pozycję bbuf_src. –

8

Jak odkryłem, coraz tablicę podkład nie zawsze działa (nie działa w przypadku buforów tylko do odczytu, buforów bezpośrednich i buforów plików odwzorowanych w pamięci). Lepszą alternatywą jest skopiowanie bufora źródłowego i ustawienie nowego limitu ilości danych, które chcesz przesłać:

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

Ale Oracle twierdzi, że limit musi być "nie większy niż pojemność bufora". Duplikowanie bufora powiela jego pojemność, prawda? –