views:

365

answers:

1

Summary: I have a ByteBuffer in which I am pumping some data. After that, I want to send this data over a Socket.

So, I wrote code like this:

    private static void serialize(ByteBuffer buffer, EmployeeData emp, CharsetEncoder encoder)
{
 // id
 buffer.putInt(emp.getId());

 CharBuffer nameBuffer = CharBuffer.wrap(emp.getFirstName().toCharArray());
 ByteBuffer nbBuffer = null;

 // length of first name
 try
 {
  nbBuffer = encoder.encode(nameBuffer);
 } 
 catch(CharacterCodingException e)
 {
  throw new ArithmeticException();
 }

 System.out.println(String.format("String [%1$s] #bytes = %2$s", emp.getFirstName(), nbBuffer.limit()));
 buffer.putInt(nbBuffer.limit());
 buffer.put(nbBuffer);

 // put lastname
 nameBuffer = CharBuffer.wrap(emp.getLastName().toCharArray());
 nbBuffer = null;

 // length of first name
 try
 {
  nbBuffer = encoder.encode(nameBuffer);   
 } 
 catch(CharacterCodingException e)
 {
  throw new ArithmeticException();
 }

 System.out.println(String.format("String [%1$s] #bytes = %2$s", emp.getLastName(), nbBuffer.limit()));
 buffer.putInt(nbBuffer.limit());
 buffer.put(nbBuffer);

 // salary
 buffer.putInt(emp.getSalary());
}

In the calling code, I do the following. I first get the serialized ByteBuffer and then write it out to the socket...

      Socket client = new Socket("localhost", 8080);

  OutputStream oStream = client.getOutputStream();

  serialize(buffer, emp, encoder);

  buffer.rewind();   
  while(buffer.hasRemaining())
  {
   byte temp = buffer.get();
   ++ written;
  }

  buffer.rewind();
  System.out.println("#Bytes in output buffer: " + written + " limit = " + buffer.limit() + " pos = " + buffer.position() + " remaining = " + buffer.remaining());

  int remaining = buffer.remaining();
  while(remaining > 0)
  {
   oStream.write(buffer.get());
   -- remaining;
  }

I am expecting that buffer.remaining() should be exactly equal to the #bytes I pumped into the buffer. However I am finding that it is not, it is always equal to 1024, which is the size of the underlying array of the buffer.

This is how I create the buffer...

     Charset charset = Charset.forName("UTF-8");
 CharsetDecoder decoder = charset.newDecoder();
 CharsetEncoder encoder = charset.newEncoder();
 byte [] underlyingBuffer = new byte[1024];
 ByteBuffer buffer = ByteBuffer.wrap(underlyingBuffer);
 buffer.order(ByteOrder.LITTLE_ENDIAN);

This is what I get as the output of my print statement...

String [John] #bytes = 4 String [Smith] #bytes = 5

#Bytes in output buffer: 1024 limit = 1024 pos = 0 remaining = 1024

How can I get the exact #bytes that were put into the buffer?

Thanks!

+3  A: 

When you are done putting bytes into the buffer, you should flip it. You can probably do this in place of your first call to 'rewind' instead.

A java.nio.Buffer distinguishes between 'capacity' and 'limit'. If you don't flip it, then limit and capacity are the same as the length of the array with which you initialized it.

By flipping it, the limit will be set to the end of the data you've encoded, capacity will still be 1024. ByteBuffer#remaining looks at the delta between position and limit.

Joe Holloway
Thanks, Joe. That fixed it.
feroze