【高分请教】JAVA位移熟悉的兄弟进

cscript 中软 开发组长/高级工程师/技术专家  2012-12-19 06:22:13

public static long readUnit64(ByteBuffer buf){
int l = 0;
long rst = 0L;
while(l<64){
int t = buf.get();
rst |= (long)((t & 127) << l);
if((t & 128) == 0)
return rst;
l += 7;
}
return 0;
}

public static void writeUnit64(ByteBuffer buf, long val){
while(true){
if ((0xFFFFFF80 & val) == 0L){
buf.put((byte)(int)val);
break;
}
buf.put((byte)(128 | 127 & (int)val));
val >>>= 7;
}
}

public static void main(String[] args) {
long t = System.currentTimeMillis()/1000; //问题在这里,不除以1000就是错的
System.out.println("原始数据:"+t);
ByteBuffer buf = ByteBuffer.allocate(128);
writeUnit64(buf, t);
buf.flip();
System.out.println("原始数据:"+readUnit64(buf));
}


如上 代码所视,小弟最近分析一socket协议 其中用到 writeUnit64 和 readUnit64 方法来用于 把一long类型的数据转换为byte和把一byte数组读取为long

当处理的long数据长度为10位的时候,这两个方法都很正常
但是 当长度为13位的时候 writeUnit64 正常 但 readUnit64 出来的数据是错的还是负数

小弟翻阅谷哥,度娘 未果,特发此贴, 希望高手解惑


PS:小弟发此贴不是为了解决怎么把long转换为byte数组,而是把writeUnit64后的数据正确的读取出来,谢谢各位
...全文
169 点赞 收藏 9
写回复
9 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
MiceRice 2012-12-20
关键就是这句:   rst |= (long)((t & 127) << l); 因为(t & 127) << l 溢出了 int 的范围,所以造成符号位。 修正方法就是要在做移位前先强转 long。 那么 4 楼直接把t定义为long,所以也是可以解决问题的。
回复
MiceRice 2012-12-20
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;
    }
回复
cscript 2012-12-20
恩 粗心了 感谢 ldh911、nmyangym 的 指导 真的感激涕零 还有dracularking同志指出的优化问题 再次感谢各位
回复
科學信仰 2012-12-20
同意楼上 (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转型貌似也没必要
回复
sjlzcj 2012-12-19
抛砖引玉一下 首先你的 writeUnit64 中的 buf.put((byte)(128 | 127 & (int)val)); 这一句 存在问题 val 你定义为long型 在这里被强转成了 int型 丢失了精度 如果没分析错的话 问题不是 多少位数字 你给的数只要大于Integer.MAX_VALUE 就出问题 long强转int 直接丢弃 前4个字节 反过来 int转long 就是根据正负数在前面加上4个字节的0或1 readUnit64方法我没看
回复
nmyangym 2012-12-19
把t改成long即可: 另外判断条件换一下,避免异常。代码:

	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.
	}
回复
aotian16 2012-12-19
不是很清楚, 不过你可以参考 1. datainputstream的readlong 2. dataoutputstream的writelong
回复
流星陨落 2012-12-19
顶一下,等大牛
回复
发帖
Java SE
创建于2007-09-28

6.1w+

社区成员

Java 2 Standard Edition
申请成为版主
帖子事件
创建了帖子
2012-12-19 06:22
社区公告
暂无公告