2011-03-12 12 views
1

我有以下哪个ID等以端口到Java无符号长在Java中,使用的BigInteger用于算法,但BigInteger.toByteArray返回14个字节,而不是8

unsigned long long* data=(unsigned long long*)pBuffer; // file data 
unsigned long long crypt = 0x0000; 
unsigned long long next_crypt; 
unsigned int len = size >> 3; 

for(unsigned int i=0; i<len;i++) { 
     next_crypt = crypt+data[i]-0xCAFEBABE;  
     data[i] = ((data[i]<<0x1d)|(data[i]>>0x23))+0xCAFEBABE; 
     data[i] = (data[i]<<0x0e)|(data[i]>>0x32); 
     data[i] = data[i] - crypt; 
     crypt = next_crypt;  

    } 

我试图端口这对java的C代码使用很长,但是这会导致负值。因此,我切换到biginteger,因为我必须做算术(位移等)。我使用BigInteger获得了所需的64位无符号长整型值,但是当我想将它转换为字节(BigInteger.toByteArray)时,它的长度是14个字节,不再是8个字节 - 所以我不能再修改我的数组/文件。我尝试使用toLongValue(),但数据不正确。

由于

+0

这是一个无符号long long - 8个字节! – Steve 2011-03-12 01:52:53

+2

如果您没有向我们展示Java版本,您希望得到答案吗? – 2011-03-12 03:35:14

回答

2

你的C代码是依靠比特移位关闭unsigned long long的高阶端。 (这些通过另一个移位绕另一端旋转。)BigInteger是任意精度,因此没有结束,所以左移位永远不会偏移。

您可以构建一个64位BigInteger按位与屏蔽并在左移之后进行AND操作。这是一个直观的解决方案。

你也可以简单地忽略高位字节。

byte[] bar = foo.toByteArray(); 
if (bar.length > 8) { 
    bar = System.arrayCopy(bar, bar.length - 8, new byte[8], 0, 8); 
} 

如果len很大,那么这个简单的解决方案会浪费内存。

在任何情况下,都有一个更好的和更高性能的解决方案。 Java的有符号整数类型都保证有两个补码语义。具有二进制补码整数和无符号整数的算术的位语义是相同的 - 区别只在于对值的解释!因此,只需使用原来的C代码(用Java的long代替)并在最后以的方式将它们解释为

byte[] longToByteArray(long x) { 
    byte[] array = new byte[8]; 
    for (int i = 7; i >= 0; i--) { 
     array[i] = (byte)x; 
     x >>>= 8; 
    } 
} 

顺便说一句,一定要更换>>运营商与Java的>>>运营商的C代码。

+1

非常感谢你,解决了我的问题 - 我不知道“>>>” - 这确实解决了我的问题。正如我所说我以前负长值,但与无符号右移运算符它工作得很好btw,是你的longToByteArray任何不同,然后ByteBuffer b = ByteBuffer.allocate(8); b.putLong(的longValue); b.array()? – Steve 2011-03-12 23:17:06

+1

@Steve,它们是相同的(因为默认情况下ByteBuffer是大端)。我没有意识到这个方案,而是肯定使用它。 – rlibby 2011-03-12 23:50:41

1

Java的好处在于它保证了二进制补码,因此只要使用>>>而不是>>并避免%和/和不等式,算术无论如何都是无效的。

+0

谢谢,与其他海报类似,解决了我的问题! – Steve 2011-03-12 23:18:20

相关问题