Java位操作错误(转换为字节并转换回)

时间:2012-08-25 05:20:50

标签: java bit operations

我正在尝试将出生日期(三个整数)转换为字节并将其转换回来,但我遇到了问题。我必须通过使用位操作转换它并通过多播服务器发送数据并接收它并更改回int。服务器工作正常,但位操作对我来说很难。代码有什么问题:

转换:

      int D=12; 
      int M=9; 
      int Y=1983;
      short DMY=0; 
      DMY = (short)(DMY | (D << 19));
      DMY = (short)(DMY | (M << 15));
      DMY = (short)(DMY | Y); 
      byte[] data = new byte[3];
      data[0] = (byte)(DMY >>> 8 );
      data[1] = (byte)(DMY >>> 16 );
      data[2] = (byte)(DMY & 0xffff);

转换回来:

           byte[] rec_data = new byte[3];
           rec_data = dp.getData();
           short Rec_dmy;


           Rec_dmy = (short)(rec_data[0] & 0xff);
           Rec_dmy = (short) (Rec_dmy << 8);
           Rec_dmy = (short)(Rec_dmy | (rec_data[1] & 0xff));
           Rec_dmy = (short) (Rec_dmy << 8);
           Rec_dmy = (short)(Rec_dmy | (rec_data[2] & 0xffff));

           byte tmp = (byte) ((Rec_dmy  >>> 19) & 0x1F);
           byte tmp2 = (byte) ((Rec_dmy >>> 15) & 0x1FF);
           byte tmp3 = (byte) (Rec_dmy & 0x7F);       

            System.out.println(tmp);
            System.out.println(tmp2);
            System.out.println(tmp3);

Println给出以下答案: 31 -1 63

它不接近原版12 9 1983

3 个答案:

答案 0 :(得分:3)

短裤只能容纳16位;你试图收集更多的东西(例如,将剩余的时间换成19,这将导致一旦变为短暂的全零值)。您需要使用int或long来保存所有字段。

实际上,你有几件事情正在进行,这些比特操作是不对的。

我的建议是放弃位操作,只将日,月和年作为单独的字段发送:每天和每月的一个字节,以及一年中的两个(短)。这需要4个字节(只需要一个额外的字节),但需要更少的摆弄才能正确。

答案 1 :(得分:1)

这并不容易,但你必须系统地工作以确保你的操作不会a)丢失信息b)解码你编码的方式。

int D = 12;
int M = 9;
int Y = 1983;
int DMY = (D << 19) | (M << 15) | Y;
byte[] data = new byte[3];
data[0] = (byte) (DMY >>> 16);
data[1] = (byte) (DMY >>> 8);
data[2] = (byte) DMY;

int DMY2 = ((data[0]&0xFF) << 16) | ((data[1]&0xFF) << 8) | (data[2]&0xFF);
int D2 = DMY2 >>> 19;          // no mask required
int M2 = (DMY2 >>> 15) & 0x0F; // 4 bits mask
int Y2 = DMY2 & 0x7FFF;        // 15 bit mask
System.out.println(D2 + "/" + M2 + "/" + Y2);

打印

12/9/1983

答案 2 :(得分:0)

首先,由于2^14 > 9999 && 2 ^ 13 < 9999,您需要至少14位来表示最大值为9999的年份。月份的最小位数为4(最多12位),日期为5(最大值为31)。因此,您可以使用short int(16位)表示每天和每月的年份和字节(8位)。所以你得到一个32位的int。

public int encoded(short year, byte month, byte day){
    int data =0;
    data = year & 0xFFFF;
    data =(data << 8)|(month & 0xFF)
    data =(data << 8)|(day & 0xFF)
    return data;
}

public void decode(int data){
    int day = data & 0xFF;
    int month = (data >> 8) & 0xFF;
    int year = (data >> 16) & 0xFFFF;
}