2012-04-21 44 views
3

我有一个long变量,我需要颠倒它的字节顺序。例如:B1, B2, ... , B8我应该返回一个包含B8, B7, ..., B1的长整数。我怎样才能通过使用按位操作?反向字节长的顺序

+0

你在使用endian-ness吗? – 2012-04-21 14:44:35

回答

6

可以使用Long.reverseBytes(long)

或者更多的方法,其中包括按位运算,你可以参考这个stack overflow question

继承人另一个你可能喜欢的方式,我还是建议以上,但它比按位好你可以轻松地犯错误。

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

我试图从按位解决方案,引导你走,因为他们是累赘,很容易乱了,如果你不知道你在做什么......但按位应该是这样的:

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

'Arrays.asList(bytes)'代码将不起作用--Array.asList(bytes)将返回一个'List ',而不是'List ' - 它将返回一个包含一个元素的列表,整个字节数组。 – 2012-04-21 17:07:41

+0

@LouisWasserman有趣的是,我在不同的网站上看到了几次弹出的片段,所以我们假定它是正确的,但是你说的没错,我会替换它。 – Serdalis 2012-04-22 03:06:58

+0

@Serdalis您的'ByteBuffer'解决方案就像一个魅力。谢谢! – Maxbester 2013-11-21 15:50:58

2

您可能想要使用Long.reverseBytes而不是按位操作。详细信息请参见Java Reference

否则,您可以看看Long.java中的JDK源文件(位于JDK文件夹中的src.zip),但请注意Oracle的版权。

+0

如果我不能使用'Long.reverseBytes'并且需要按位操作来完成呢? – Aviram 2012-04-21 14:37:45

+0

@BenM:你为什么不能使用它? – home 2012-04-21 14:55:28

+0

@BenM在我的答案中添加了一个指向JDK源的指针。在'Long.reverseBytes'中,它是通过按位操作完成的。 – Matthias 2012-04-21 15:05:08

1

这里是一个老把戏,你可以用它来交换尾段寄存器:

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

的想法是,直到达到您想要停止在所需的水平,逐步换子块。通过添加大小为4,2和1的交换,您可以将其更改为位镜像功能。

由于缺少java中的无符号类型,只有一个棘手的问题。在向右移位时需要屏蔽高位,因为符号位被移位量复制,用高位位填充1(0x8000000000000000 >> 80xFF80000000000000)。

0
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; 
} 

如果我们假设位运算符在O(1)时间工作,反向函数工作在O(LG(比特数))的时间。

说明
步骤0:B1 B2 B3 B4 B5 B6 B7 B8
第1步:B5 B6 B7 B8 B1 B2 B3 B4
步骤2:B7 B8 B5 B6 B3 B4 B1 B2
第3步:B8 B7 B6 B5 B4 B3 B2 B1

0

平原答案与循环:只有

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

按位:

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