我有一个long类型变量,应保存到字节缓冲区。因为在Java中,所有int值都适合4个字节,所有长值都存储在8个字节中,并且我可以访问一个简单的函数,它将整数保存为4个字节,我提出了这个解决方案:
public class TestApp {
static byte [] buffer = new byte[8];
static public void writeInt(int startIndex, int number) {
buffer[startIndex] = (byte) (number >> 24);
buffer[startIndex + 1] = (byte) (number >> 16 & 0x000000FF);
buffer[startIndex + 2] = (byte) (number >> 8 & 0x000000FF);
buffer[startIndex + 3] = (byte) (number & 0x000000FF);
}
static public int readInt(int startIndex) {
return
(buffer[startIndex] & 0xFF) << 24 |
(buffer[startIndex+1] & 0xFF) << 16 |
(buffer[startIndex+2] & 0xFF) << 8 |
(buffer[startIndex+3] & 0xFF);
}
static public void writeLong(int startIndex, long number) {
writeInt(startIndex, (int)(number >> 32));
writeInt(startIndex + 4, (int)number);
}
static public long readLong(int startIndex) {
long a1 = readInt(startIndex);
long a2 = readInt(startIndex+4);
long b= a1 << 32;
b |= a2;
return b;
}
public static void main(String []args) {
long r = 817859255185602L;
writeLong(0, r);
long test = readLong(0);
System.out.println(Long.toString(r));
System.out.println(Long.toString(test));
}
}
令人惊讶地发现readLong()
实际上没有做到它应该做的事情。我在写readLong()
和writeLong()
时的想法是,当向左移动一个Integer值32位,然后用下一个整数移动结果时;结果将成为所需的长值。但这个样本证明我错了。或者两个整数有什么问题?
答案 0 :(得分:5)
你的问题在于这一部分:
long a1 = readInt(startIndex);
long a2 = readInt(startIndex+4);
readInt
会返回int
。这会自动转换为long。转换为long不会简单地添加四个字节的零。它将符号位向左扩展。
在这种情况下,a2
为0xb261b0c2
。这意味着它最重要的位 - 符号位 - 为1.因此它被扩展为长0xffffffffb261b0c2
。
当然,当您使用移位的a1
进行OR时,结果将始终为0xffffffff________
。
你应该做的是
long a2 = readInt(startIndex+4) & 0xffffffffL;
这将确保a2
的最重要的四个字节将保持为零,因此当您将它们与移位的a1
进行OR时,它将保持中立。
答案 1 :(得分:0)
RealSkeptic的回答是正确的。在我看来,你正试图重新发明轮子。例如。 Guava已经在long / int / ...和byte数组之间进行了转换:
long r = 817859255185602L;
byte[] buffer = Longs.toByteArray(r);
long test = Longs.fromByteArray(buffer);