Reverse bytes order of long

2019-05-13 01:04发布

问题:

I've got a long variable and I need to reverse its byte order. For example: B1, B2, ... , B8 I should return a long that consists of B8, B7, ..., B1. How can I do it by using bitwise operations?

回答1:

you can use Long.reverseBytes(long)

Or for more methods which include bitwise operations, you can refer to this stack overflow question

Heres another method you may like, I'd still recommend the above but it's better than bitwise where you can easily make mistakes.

Bytebuffer

byte[] bytes = ByteBuffer.allocate(8).putLong(someLong).array();
for (int left = 0, right = bytes.length - 1; left < right; ++left, --right) {
    byte temp = bytes[left]; 
    bytes[left]  = bytes[right]; 
    bytes[right] = temp;
}

I am trying to steer you away from bitwise solutions because they are cumbersome and very easy to mess up if you do not know what you are doing... But bitwise would look like this:

byte[] bytes = new byte[8];

// set the byte array from smallest to largest byte
for(int i = 0; i < 8; ++i) {
    byte[i] = (your_long >> i*8) & 0xFF;
}

// build the new long from largest to smallest byte (reversed)
long l = ((buf[0] & 0xFFL) << 56) |
         ((buf[1] & 0xFFL) << 48) |
         ((buf[2] & 0xFFL) << 40) |
         ((buf[3] & 0xFFL) << 32) |
         ((buf[4] & 0xFFL) << 24) |
         ((buf[5] & 0xFFL) << 16) |
         ((buf[6] & 0xFFL) <<  8) |
         ((buf[7] & 0xFFL) <<  0) ;


回答2:

You might want to use Long.reverseBytes instead of using bitwise operations. See the Java Reference for details.

Otherwise, you could have a look at the JDK sources (src.zip in your JDK folder) in Long.java but mind the copyright by Oracle.



回答3:

Here's an old trick that you can use to endian swap a register:

static long swapblock(long a, long mask, int shift) {
    long b1 = a & mask; // extract block
    long b2 = a ^ b1;   // extract remaining bits
    return (b1 << shift) |
           ((b2 >> shift) & mask); // mask again to clear sign extension
}

static long endianswap(long a) {
    a = swapblock(a, 0x00000000ffffffffL, 32);
    a = swapblock(a, 0x0000ffff0000ffffL, 16);
    a = swapblock(a, 0x00ff00ff00ff00ffL, 8);
    return a;
}

The idea is to progressively swap sub blocks until you reach the desired level you want to stop at. By adding swaps of sizes 4, 2, and 1, you can change this into a bit mirror function.

There is only one tricky bit due to lack of unsigned types in java. You need to mask out high order bits when shifting right, because the sign bit is replicated by the shift amount, filling the high order bits with ones (0x8000000000000000 >> 8 is 0xFF80000000000000).



回答4:

long reverse(long x){
     x = (x >> 32) | (x << 32); // step 1
     x = ((x & 0xffff0000ffff0000 ) >> 16) 
          | ((x & 0x0000ffff0000ffff ) << 16); // step 2
     x = ((x & 0xff00ff00ff00ff00 ) >> 8) 
          | ((x & 0x00ff00ff00ff00ff ) << 8); // step 3
     return x;
}

If we assume that bitwise operator works in O(1) time, reverse function works in O(lg(number of bits) ) time.

Explanation
Step 0 : B1 B2 B3 B4 B5 B6 B7 B8
Step 1 : B5 B6 B7 B8 B1 B2 B3 B4
Step 2 : B7 B8 B5 B6 B3 B4 B1 B2
Step 3 : B8 B7 B6 B5 B4 B3 B2 B1



回答5:

Plain answer with loops:

public static long byteReverse(long a) {

    long result = 0;
    for(int i = 0; i < 8; i++){
        // grab the byte in the ith place
        long x = (a >> (i*8)) & (0b11111111);
        result <<= 8;
        result |= x;
    }
    return result;
}

bitwise only:

public static long byteReverse(long a) {

    a = (a << 32) | (a >>> 32);
    a = ((a & 0xffff0000ffff0000L) >>> 16) | ((a & 0x0000ffff0000ffffL) << 16);
    a = ((a & 0x00ff00ff00ff00ffL) << 8) | ((a & 0xff00ff00ff00ff00L) >>> 8);

    return a;
}