0

The following code attempts to store 4 longs in a byte array. Random access is important which is why I'm not doing this with byte streams. Why is the below code not working? Can you think of a more efficent 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 output I get from the above is the following. You can see that the first four numbers do not match the next 4:

-1
1
9223372036854775807
-9223372036854775808

-72340172838076673
1
9151031864016699135
-9223372036854775808
5
  • 3
    What is not working? What result do you get, and what result do you expect? Commented Apr 17, 2012 at 19:19
  • Well you should be able to use loops in lines like this: buf[offset+2] = (byte) ((value >>> 16) & 0xFFL); Commented Apr 17, 2012 at 19:20
  • What's the compile error msg? Commented Apr 17, 2012 at 19:20
  • I've updated the post with the output. @Adel I don't see that a loop would add any efficiency here Commented Apr 17, 2012 at 19:25
  • The "right" way to do this would be to use ByteBuffer. Commented Apr 17, 2012 at 19:27

2 Answers 2

8

Don't use + and byte is signed:

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 have to and each byte with 255 to make it 'unsigned'. Also you have to use binary or instead of add.

Sign up to request clarification or add additional context in comments.

Comments

2

I did some tests and found that using a 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));

I can then get the byte array using bb.array()

Thanks to Louis Wasserman and Rene Jeschke for their efforts

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.