将位转换为整数

时间:2012-07-10 18:23:20

标签: java bytearray endianness

我收到一个包含字节数组的数据包,我必须从中获取一些整数值。 这是文档的一部分。有人能帮帮我吗?

这是一个4字节的数组。

  

1990年至2052年(6位),1月12日(4位),1日   到31(5位),小时从0到23(5位),分钟从0到59(6位),   秒数从0到59(6位)默认值:2000年1月1日,12:00

邮件的格式是小端。

3 个答案:

答案 0 :(得分:3)

您需要的是一些按位操作。首先,用字节构造一个int:

int n = b[0] | (b[1] << 8) | (b[2] << 16) | (b[3] << 24);

然后,将int切入组件中。现在,您的问题没有指定字段的方式,从右到左或从左到右。这个问题与字节序有关,但不完全相同。所以我们假设这些字段从左到右。

良好的意识表明从左到右。通过这种方式,可以比较时间值的整数表示 - 年份位的重要性大于月份位等,因此当您比较对应于两个时刻的整数时,您将获得按时间顺序排列的正确结果。

这是一个适合你的心理形象。这是一个整数变量,由位组成:

f e d c b a 9 8 7 6 5 4 3 2 1 0
            -----
              offset is 6, length is 3

让我们定义一个函数,该函数从给定偏移量(以位为单位)的int中获取任意块,具有给定长度(以位为单位)。

int bits(int n, int offset, int length)
{
    //shift the bits rightward, so that the desired chunk is at the right end
    n = n >> (31 - offset - length); 

    //prepare a mask where only the rightmost `length`  bits are 1's
    int mask = ~(-1 << length);

    //zero out all bits but the right chunk
    return n & mask;
}

可能是一个单行,但我想让它有点具有启发性。通过为每个块手动指定移位因子和掩码,下面答案中的人员可以有效地内联此功能。

现在让我们分解。假设n来自最顶端的片段:

int year  = bits(n, 0,  6),
    month = bits(n, 6,  4),
    day   = bits(n, 10, 5),
    hour  = bits(n, 15, 5),
    min   = bits(n, 20, 6),
    sec   = bits(n, 26, 6);

我们通过将前一个字段的总长度组合在一起来获得偏移的值。这是假设田地从左到右;如果它们相反,偏移值将会不同。

这有意义吗?

编辑:如果比特块从右到左,那么这就是它的方式:

int sec   = bits(n, 0,  6),
    min   = bits(n, 6,  6),
    hour  = bits(n, 12, 5),
    day   = bits(n, 17, 5),
    month = bits(n, 22, 4),
    year  = bits(n, 26, 6);

答案 1 :(得分:1)

首先,我将其转换为整数:

import java.nio.ByteBuffer;
import java.nio.ByteOrder;

int timestamp = ByteBuffer.wrap(byte_array).order(ByteOrder.LITTLE_ENDIAN).getInt();

接下来,我将它拆开:

int yearCode  = (timestamp >> 26) & 0b111111;
int monthCode = (timestamp >> 22) & 0b1111;
int dayCode   = (timestamp >> 17) & 0b11111;
int hourCode  = (timestamp >> 12) & 0b11111;
int minCode   = (timestamp >> 6)  & 0b111111;
int secCode   = (timestamp >> 0)  & 0b111111;

第一行中的屏蔽和最后一行的移位并非绝对必要,但为了清楚起见,请保留。

最后一步是向yearCode添加1900,你就完成了!

答案 2 :(得分:0)

假设您有java 7,您应该能够将年份视为

    int year = 1990
    + ((b[0] & 0b1000_0000) << 5)
    + ((b[0] & 0b0100_0000) << 4)
    + ((b[0] & 0b0010_0000) << 3)
    + ((b[0] & 0b0001_0000) << 2)
    + ((b[0] & 0b0000_1000) << 1)
    + ((b[0] & 0b0000_0100));

和月份

    int month = 1 
    + ((b[0] & 0b1000_0010) << 3)
    + ((b[0] & 0b0100_0001) << 2)
    + ((b[1] & 0b1000_0000) << 1)
    + ((b[1] & 0b0100_0000));

我让你以同样的方式做其他人。

我没有java7而现在无法测试,希望我没错。字节的顺序也可能是反向的。