5楼的同学误会了,楼主的程序只使用了 7 个 bit 来进行存储,所以安全绕过符号位。楼主程序的核心问题是强转 long 的时机错误,修正如下: public static long readUnit64fix(ByteBuffer buf) { int l = 0; long rst = 0L; while (l < 64) { int t = buf.get(); rst |= ((long) (t & 0x7f) << l); // 只是这句话而已 if ((t & 0x80) == 0) return rst; l += 7; } return 0; }
关键就是这句: rst |= (long)((t & 127) << l); 因为(t & 127) << l 溢出了 int 的范围,所以造成符号位。修正方法就是要在做移位前先强转 long。那么 4 楼直接把t定义为long,所以也是可以解决问题的。
同意楼上(t & 127) << l 这操作是在int范围内进行的,如果期望值大于32位,它仍无法自动拓展成long型有些地方貌似还可以再优化一下 int t = buf.get(); //这里int改为byte较好 buf.put((byte)(int)val); //这里的int转型貌似没必要 buf.put((byte)(128 | 127 & (int)val)); //这里int转型貌似也没必要
不过你可以参考
1. datainputstream的readlong
2. dataoutputstream的writelong
另外判断条件换一下,避免异常。代码: public static long readUnit64(ByteBuffer buf){
int l = 0;
long rst = 0L;
//while(l<64){
while(buf.position()<buf.limit()){//换一下判断条件
long t = (int)buf.get();//t改成long
rst |= (t & 127) << l;
if((t & 128) == 0)
return rst;
l += 7;
}
return rst;//返回rst.
}
buf.put((byte)(128 | 127 & (int)val));
这一句 存在问题 val 你定义为long型 在这里被强转成了 int型 丢失了精度 如果没分析错的话 问题不是 多少位数字
你给的数只要大于Integer.MAX_VALUE 就出问题long强转int 直接丢弃 前4个字节反过来 int转long 就是根据正负数在前面加上4个字节的0或1readUnit64方法我没看
int l = 0;
long rst = 0L;
while (l < 64) {
int t = buf.get();
rst |= ((long) (t & 0x7f) << l); // 只是这句话而已
if ((t & 0x80) == 0)
return rst;
l += 7;
}
return 0;
}
rst |= (long)((t & 127) << l);
因为(t & 127) << l 溢出了 int 的范围,所以造成符号位。修正方法就是要在做移位前先强转 long。那么 4 楼直接把t定义为long,所以也是可以解决问题的。
int t = buf.get(); //这里int改为byte较好
buf.put((byte)(int)val); //这里的int转型貌似没必要
buf.put((byte)(128 | 127 & (int)val)); //这里int转型貌似也没必要