2009-02-20 11 views
5

Was ist der effizienteste Weg, um so viele Bytes wie möglich von einem ByteBuffer in einen anderen ByteBuffer bbuf_dest (sowie wissen, wie viele Bytes wurden übertragen)? Ich versuche bbuf_dest.put(bbuf_src), aber es scheint zu wollen, eine BufferOverflowException zu werfen, und ich kann nicht die Javadocs von Sun im Moment (Netzwerkprobleme), wenn ich sie brauche. > :(arghÜbertragung von Bytes von einem ByteBuffer zu einem anderen


bearbeiten. Darnit, @ Richard Ansatz (Verwendung put() von den Trägern Array von bbuf_src) funktioniert nicht, wenn bbuf_src ein Readonly-Puffer ist, wie Sie keinen Zugang bekommen dass Array. Was kann ich in diesem Fall tun ???

+0

Ich denke, Sie sollten dies in zwei Fragen aufteilen. – GEOCHET

+0

die andere Hälfte wurde hier verlegt: http://StackOverflow.com/Questions/570218/Downloading-Sun-Javadocs-Mirror-Websites –

Antwort

1

OK, ich habe @ Richard Antwort angepasst:

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

und ein Test, um sicherzustellen, es funktioniert:

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

Sie erhalten die BufferOverflowException weil Ihr bbuf_dest nicht groß genug ist.

Sie müssen bbuf_dest.remaining() verwenden, um die maximale Anzahl an, um herauszufinden, Bytes, die Sie von bbuf_src übertragen können:

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

Ah. Das ist hilfreich. Ich denke ich weiß was ich jetzt tun soll. Vielen Dank. Beachten Sie jedoch, dass Ihre Antwort nicht funktioniert, wenn bbuf_src ein Ansichtspuffer für einen anderen Puffer ist. Ich denke, ich kann es aber anpassen. –

+0

(oder wenn die Position von bbuf_src> 0 ist) –

+0

... und ich muss auch die Position von bbuf_src aktualisieren. –

8

Wie Sie entdeckt haben, hat die Unterstützung Array bekommen nicht immer funktionieren (es schlägt für schreibgeschützte Puffer, direkte Puffer und speicherabgebildete Dateipuffer fehl). Die bessere Alternative besteht darin, Ihren Quellpuffer zu duplizieren und ein neues Limit für die Menge der Daten festzulegen, die Sie übertragen möchten:

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

Aber Oracle sagt, dass die Grenze "nicht größer als Pufferkapazität" sein muss. Duplizieren eines Puffers wird seine Kapazität duplizieren, oder? –