tags:

views:

162

answers:

2

What's the most efficient way to put as many bytes as possible from a ByteBuffer bbuf_src into another ByteBuffer bbuf_dest (as well as know how many bytes were transferred)? I'm trying bbuf_dest.put(bbuf_src) but it seems to want to throw a BufferOverflowException and I can't get the javadocs from Sun right now (network problems) when I need them. >:( argh.


edit: darnit, @Richard's approach (use put() from the backing array of bbuf_src) won't work if bbuf_src is a ReadOnly buffer, as you can't get access to that array. What can I do in that case???

+1  A: 

You get the BufferOverflowException because your bbuf_dest is not big enough.

You will need to use bbuf_dest.remaining() to find out the maximum number of bytes you can transfer from bbuf_src:

int maxTransfer = Math.min(bbuf_dest.remaining(), bbuf_src.remaining());
bbuf_dest.put(bbuf_src.array(), 0, maxTransfer);
Richard
Ah. That's helpful. I think I know what to do now. Thanks. But note that your answer won't work if bbuf_src is a view buffer for another buffer. I think I can adapt it though.
Jason S
(or if bbuf_src's position is > 0)
Jason S
...and I also have to update bbuf_src's position.
Jason S
A: 

OK, I've adapted @Richard's answer:

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

and a test to make sure it works:

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