Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to find out total number of bytes stored in ByteBuffer?

I am trying to extract total number of bytes I have stored in my ByteBuffer data_record_value.

Below is how we representdata_record_value as one Byte Array and then write to our database from Java code.

Offset   Length (in bytes)          Purpose

0           2                       - clientId byte array
2           8                       - value of lastModifiedDate
2+8         4                       - length of avroBinaryValue array
2+8+4       Y                       - avroBinaryValue array

And this is the way I am extracting it from database -

ByteBuffer data_record_value = r.getBytes("data_record_value");

// now how do I extract total number of bytes I have stored in data_record_value?

After doing some research I found out multiple ways of extracting the total number of bytes stored in my ByteBuffer data_record_value and I am not sure which one is right?

First way is :

byte[] b = new byte[data_record_value.remaining()];
record_value.get(b);

// this will be in bytes right?
System.out.println("Byte Array Length: " + b.length);

Second way is :

int numberOfBytesInRecord = data_record_value.limit();

Third way is :

int numberOfBytesInRecord = data_record_value.remaining();

But the numbers from all the above ways doesn't match at all with each other? I am not sure which one I should use? I need to extract total number of bytes stored in data_record_value.

To cross check, we can extract individual fields from data_record_value ByteBuffer and calculate the total bytes we are storing and compare with any of the above ways.

// clientId (of two bytes by using short)
short extractClientId = data_record_value.getShort();

// lastModifiedDate ( of 8 bytes which can be long )
long extractLastModifiedDate = data_record_value.getLong();

int extractAvroBinaryValueLength = data_record_value.getInt();

byte[] extractAvroBinaryValue = new byte[extractAvroBinaryValueLength];

data_record_value.get(extractAvroBinaryValue); // read attributeValue from the remaining buffer

System.out.println(extractClientId);
System.out.println(extractLastModifiedDate);
System.out.println(new String(extractAvroBinaryValue));

Update:-

On one of the ByteBuffer data_record_value, this is what I printed out -

System.out.println("Record Value Capacity: " + data_record_value.capacity());
System.out.println("Record Value Position: " + data_record_value.position());
System.out.println("Record Value Limit: " + data_record_value.limit());
System.out.println("Record Value Remaining: " + data_record_value.remaining());
System.out.println("Record Value: " + data_record_value);

And this is what got printed -

Record Value Capacity: 387
Record Value Position: 185
Record Value Limit: 250
Record Value Remaining: 65
Record Value: java.nio.HeapByteBuffer[pos=185 lim=250 cap=387]
like image 630
john Avatar asked Feb 10 '23 19:02

john


1 Answers

When using ByteBuffer there is a difference between putting and getting values from the buffer.

When bytes are put on the buffer they get added at the current position. If the limit is reached then the buffer is full. So position() shows the amount of data in the buffer and remaining() shows how many bytes can still be put on the buffer. I'm assuming here that the data to be considered starts at position 0 (this should normally be the case).

When bytes are retrieved from the buffer then the buffer usually has been "flipped". This means that the position is set to 0 and that the limit is set to the old position. Now the value returned by position() shows how many bytes are already retrieved and remaining() shows how many bytes haven't yet been retrieved.


In your example you get a pre-existing buffer returned. The database puts data in this buffer and puts the position at the location of the data and the limit at the byte after the end of the data. So the database puts the data in the buffer and then flips the buffer.

If the position() is not set to 0 then the database may use a more advanced scheme for buffering data, but the idea that the position is at the start of the data and the limit at the end stays the same.

The total amount of data in the buffer is therefore returned by ByteBuffer.remaining() before you retrieve any data from the buffer using a relative get method.

This information is lost once you start retrieving information (although there are of course methods of getting it back, e.g. by using mark() and reset()). If you however need this information later in the process you can simply store it in a local variable or field:

int received = buffer.remaining();
like image 197
Maarten Bodewes Avatar answered Feb 13 '23 20:02

Maarten Bodewes