Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ByteBuffer Little Endian insert not working

I have to make a two way communication between a legacy system and an android device. The legacy system uses little endian byte ordering. I have successfully implemented the receiving part, however sending not works.

Strange because for me it seems that the ByteBuffer class malfunctions (I can hardly believe that)

    ByteBuffer byteBuffer = ByteBuffer.allocate(4);
    byteBuffer.order(ByteOrder.LITTLE_ENDIAN);
    byteBuffer = ByteBuffer.allocate(4);
    byteBuffer.putInt(88);
    byte[] result = byteBuffer.array();

Results: [0, 0, 0, 88]

    ByteBuffer byteBuffer = ByteBuffer.allocate(4);
    byteBuffer.order(ByteOrder.BIG_ENDIAN);
    byteBuffer = ByteBuffer.allocate(4);
    byteBuffer.putInt(88);
    byte[] result = byteBuffer.array();

Also results the same: [0, 0, 0, 88]

However if I'm not mistaken little endian ordering should return: [88, 0, 0, 0]

So what's the point I'm missing?

like image 815
Sandor Avatar asked Nov 25 '12 17:11

Sandor


People also ask

What is the byte order of ByteBuffer?

By default, the order of a ByteBuffer object is BIG_ENDIAN. If a byte order is passed as a parameter to the order method, it modifies the byte order of the buffer and returns the buffer itself. The new byte order may be either LITTLE_ENDIAN or BIG_ENDIAN.

What is ByteBuffer in Java?

ByteBuffer holds a sequence of integer values to be used in an I/O operation. The ByteBuffer class provides the following four categories of operations upon long buffers: Absolute and relative get method that read single bytes. Absolute and relative put methods that write single bytes.

How do I get ByteBuffer length?

After you've written to the ByteBuffer, the number of bytes you've written can be found with the position() method. If you then flip() the buffer, the number of bytes in the buffer can be found with the limit() or remaining() methods.

What is the little endian order of bytes?

A byte order is called little endian if the bytes of a multi-byte value are stored from the least significant byte to the most significant byte. Little endian means least significant first. In the little endian byte order, you would store 300 as 0010110000000001, which seems backwards for representing a 16-bit value.

How to get and set the byte order of a ByteBuffer?

By default, the byte order of the ByteBuffer class is always ByteOrder.BIG_ENDIAN. And, we can use the order () and order (ByteOrder) methods to respectively get and set the current byte order. The byte order influences how to interpret the underlying data. For example, suppose we have a buffer instance:

How do I create a ByteBuffer instance?

The ByteBuffer is an abstract class, so we can't construct a new instance directly. However, it provides static factory methods to facilitate instance creation. Briefly, there are two ways to create a ByteBuffer instance, either by allocation or wrapping: 2.1. Allocation

How to check if a ByteBuffer has an accessible backing array?

To be precise, the hasArray () method can tell us if a buffer has an accessible backing array or not. If the hasArray () method returns true, then we can use the array () and arrayOffset () methods to get more relevant information. 7.3. Byte Order By default, the byte order of the ByteBuffer class is always ByteOrder.BIG_ENDIAN.


2 Answers

You are, for some strange reason, reinitializing your byte buffers and throwing away the previous copies where you had changed the endian order. The following code works just fine for me:

ByteBuffer byteBuffer = ByteBuffer.allocate(4);
byteBuffer.order(ByteOrder.BIG_ENDIAN);
byteBuffer.putInt(88);
byte[] result = byteBuffer.array();
System.out.println(Arrays.toString(result));

Prints [0, 0, 0, 88]

ByteBuffer byteBuffer = ByteBuffer.allocate(4);
byteBuffer.order(ByteOrder.LITTLE_ENDIAN);
byteBuffer.putInt(88);
byte[] result = byteBuffer.array();
System.out.println(Arrays.toString(result));

Prints [88, 0, 0, 0]

like image 186
Perception Avatar answered Oct 13 '22 10:10

Perception


On a related note:

This code:

 int unicodePointsLen = textContent.length() * 2;
 ByteBuffer unicodePointsBuffer = ByteBuffer.allocateDirect(unicodePointsLen);
 short unicodePointValue;
 for (int i = 0; i < textContent.length(); i++) 
 {  
     unicodePointValue = (short)textContent.charAt(i);
     unicodePointsBuffer.put((byte)(unicodePointValue & 0x00FF)).put((byte)(unicodePointValue >> 8));
 }

Is about 25% faster than this:

 int unicodePointsLen = textContent.length() * 2;
 ByteBuffer unicodePointsBuffer = ByteBuffer.allocateDirect(unicodePointsLen);
 unicodePointsBuffer.order(ByteOrder.LITTLE_ENDIAN);
 for (int i = 0; i < textContent.length(); i++) 
 {  
     unicodePointsBuffer.putShort((short)textContent.charAt(i));  
 }

Using JDK 1.8.

I am trying to pass unicode points from JAVA to C++ through JNI and the first method is the fastest I found. Curious that it is faster than the second snippet.

like image 33
Stefano Emiliozzi Avatar answered Oct 13 '22 11:10

Stefano Emiliozzi