Java bitwise operator not working as expected
The following code tries to store 4 longs in a byte array. Random access is important, which is why I don't do it with byte streams. Why is the below code not working? Can you think of a more efficient way to do this?
public static void storeLong(long value, byte[] buf, int offset) {
buf[offset] = (byte) (value & 0xFFL);
buf[offset+1] = (byte) ((value >>> 8) & 0xFFL);
buf[offset+2] = (byte) ((value >>> 16) & 0xFFL);
buf[offset+3] = (byte) ((value >>> 24) & 0xFFL);
buf[offset+4] = (byte) ((value >>> 32) & 0xFFL);
buf[offset+5] = (byte) ((value >>> 40) & 0xFFL);
buf[offset+6] = (byte) ((value >>> 48) & 0xFFL);
buf[offset+7] = (byte) ((value >>> 56) & 0xFFL);
}
public static long retrieveLong(byte[] buf, int offset) {
return ((long)buf[offset])
+ (((long)buf[offset+1])<<8)
+ (((long)buf[offset+2])<<16)
+ (((long)buf[offset+3])<<24)
+ (((long)buf[offset+4])<<32)
+ (((long)buf[offset+5])<<40)
+ (((long)buf[offset+6])<<48)
+ (((long)buf[offset+7])<<56);
}
public static void main(String[] args) {
byte[] buf = new byte[32];
storeLong(-1, buf, 0);
storeLong(1, buf, 8);
storeLong(Long.MAX_VALUE, buf, 16);
storeLong(Long.MIN_VALUE, buf, 24);
System.out.println(-1);
System.out.println(1);
System.out.println(Long.MAX_VALUE);
System.out.println(Long.MIN_VALUE);
System.out.println(retrieveLong(buf, 0));
System.out.println(retrieveLong(buf, 8));
System.out.println(retrieveLong(buf, 16));
System.out.println(retrieveLong(buf, 24));
}
The result obtained from the above is as follows. You can see that the first four numbers don't match the next 4:
-1
1
9223372036854775807
-9223372036854775808
-72340172838076673
1
9151031864016699135
-9223372036854775808
source to share
I did some tests and found that using java.nio.LongBuffer is twice as fast as my code
ByteBuffer bb = ByteBuffer.allocate(4*8);
LongBuffer lb = bb.asLongBuffer();
lb.put(0, -1);
lb.put(1, 1);
lb.put(2, Long.MAX_VALUE);
lb.put(3, Long.MIN_VALUE);
System.out.println(lb.get(0));
System.out.println(lb.get(1));
System.out.println(lb.get(2));
System.out.println(lb.get(3));
Then I can get the byte array using bb.array ()
Thanks to Ludovic Wassermann and René Jeschke for their efforts
source to share
Don't use +
and byte
:
public static long retrieveLong(byte[] buf, int offset) {
return ((long)buf[offset] & 255)
| (((long)buf[offset + 1] & 255) << 8)
| (((long)buf[offset + 2] & 255) << 16)
| (((long)buf[offset + 3] & 255) << 24)
| (((long)buf[offset + 4] & 255) << 32)
| (((long)buf[offset + 5] & 255) << 40)
| (((long)buf[offset + 6] & 255) << 48)
| (((long)buf[offset + 7] & 255) << 56);
}
You must have and
every byte with 255 to make it "unsigned". Also you should use binary or
instead of append.
source to share