Ephemeral
Ephemeral

Reputation: 423

JAVA , unable to Byte ReOrder

I am new to Java programming, I try to write this function (debug) as a learning exercise but it does not work and I do not understand why:

FUNCTION

public static void ByteReOrder(){
 byte[] byte_array_uid = new byte[] { (byte)0x3A, (byte)0x2B, (byte)0x07 };
 out.println("UID ("+ByteOrder.nativeOrder()+"): " + HumanReprByteToHex(byte_array_uid));

 if(Byte.nativeOrder() == ByteOrder.LITTLE_ENDIAN){
   ByteBuffer byte_buffer_uid = ByteBuffer.wrap(byte_array_uid);
   out.println("Default ByteOrder is LITTLE_ENDIAN, change for BIG_ENDIAN ...");
   byte_buffer_uid.order(ByteOrder.BIG_ENDIAN);

   byte[] byte_array_from_byte_buffer_uid = new byte[byte_buffer_uid.remaining()];
   byte_buffer_uid.get(byte_array_from_byte_buffer_uid);
   out.println("UID ("+byte_buffer_uid.order()+") : " + HumanReprByteToHex(byte_array_from_byte_buffer_uid));
 }else{
   out.println("UID (LITTLE_ENDIAN): " + HumanReprByteToHex(byte_array_uid));
 }
}

OUTPUT

 UID (LITTLE_ENDIAN): 0x3A 0x2B 0x07 
 Default ByteOrder is LITTLE_ENDIAN, change for BIG_ENDIAN ... 
 UID (BIG_ENDIAN)   : 0x3A 0x2B 0x07

Result is always in LITTLE ENDIAN but byte_buffer_uid.order() appears to be correct, i block ...

ATTEMPT RESULT

0x07 0x2B 0x3A

Thank you in advance.

Upvotes: 2

Views: 767

Answers (2)

Peter Lawrey
Peter Lawrey

Reputation: 533492

The default byteOrder() is already BIG_ENDIAN so setting it won't even change the ByteBuffer itself. Even if you were to alter the byteOrder this is just a setting on how to read/write multi-byte values. It doesn't change the order of individual bytes only how they are read or written when you do a multi-byte operation.

public static void main(String[] args) {
    byte[] bytes = {1, 2, 3, 4, 5, 6, 7, 8};
    ByteBuffer bb = ByteBuffer.wrap(bytes);
    print(bb.order(ByteOrder.BIG_ENDIAN));
    print(bb.order(ByteOrder.LITTLE_ENDIAN));
}

private static void print(ByteBuffer bb) {
    System.out.println("With " + bb.order() + " byte order");
    for (int i = 0; i < bb.capacity(); i++)
        System.out.println("byte " + i + ": " + bb.get(i));
    for (int i = 0; i < bb.capacity() - 2; i++)
        System.out.println("short " + i + ": " + Integer.toHexString(bb.getShort(i)));
    for (int i = 0; i < bb.capacity() - 3; i++)
        System.out.println("int " + i + ": " + Integer.toHexString(bb.getInt(i)));
}

prints

With BIG_ENDIAN byte order
byte 0: 1
byte 1: 2
byte 2: 3
byte 3: 4
byte 4: 5
byte 5: 6
byte 6: 7
byte 7: 8
short 0: 102
short 1: 203
short 2: 304
short 3: 405
short 4: 506
short 5: 607
int 0: 1020304
int 1: 2030405
int 2: 3040506
int 3: 4050607
int 4: 5060708
With LITTLE_ENDIAN byte order
byte 0: 1
byte 1: 2
byte 2: 3
byte 3: 4
byte 4: 5
byte 5: 6
byte 6: 7
byte 7: 8
short 0: 201
short 1: 302
short 2: 403
short 3: 504
short 4: 605
short 5: 706
int 0: 4030201
int 1: 5040302
int 2: 6050403
int 3: 7060504
int 4: 8070605

When you write an int,a long or a float to the ByteBuffer it doesn't know you wrote these types, only that you wrote bytes. This means when you changes the ByteOrder setting, it cannot alter the underlying data as it don't know if the first 8 bytes are a double, two int, 4 short or 8 bytes.

The only way this will do anything is when you read the data with their original types. It is only at this point that the code will do something to the order of the bytes.

BTW The native order is BIG_ENDIAN on some machines.

Upvotes: 2

Ferdinand Neman
Ferdinand Neman

Reputation: 700

From the java doc

This class defines methods for reading and writing values of all other primitive types, except boolean. Primitive values are translated to (or from) sequences of bytes according to the buffer's current byte order, which may be retrieved and modified via the order methods. Specific byte orders are represented by instances of the ByteOrder class. The initial order of a byte buffer is always BIG_ENDIAN.

Means the default of ByteBuffer (and Java) is always BIG_ENDIAN. And this will effect the getter and setter method of primitive types (short, int, long, float and double).

Invoking get(array) or array() only will get the backing copy of the byte array, it will not reflect any ordering.

Try to compare the byte array after you "put" some primitive value, before and after you put different ordering.

ByteBuffer bb = new ByteBuffer();
bb.order(ByteOrder.BIG_ENDIAN);
bb.putFloat(1234.123f);
byte[] bytesOne = bb.array();

bb.clear();
bb.order(ByteOrder.LITTLE_ENDIAN);
bb.putFloat(1234.123f);
byte[] bytesTwo = bb.array();

// compare betwee bytesOne and bytesTwo to see different byte ordering.

Upvotes: 3

Related Questions