Reverse bytes order of long

六眼飞鱼酱① 提交于 2019-12-05 21:35:11
Serdalis

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) ;

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.

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).

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

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;
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!