Java中字节数组的位移操作

k.k*_*ken 5 java bit-manipulation

如何将字节数组n位置向右移位?例如,将一个16字节数组右移29个位置?我在某个地方看过它可以用很长的时间来完成吗?会使用这样的长期工作:

长k1 =从0到7的字节数组

长k2 =从8到15的字节数组

然后使用Long.rotateRight(长x,旋转次数)右旋这两个long.如何将两个long连接回一个字节数组?

Ada*_*dam 12

我相信你可以使用java.math.BigInteger来做到这一点,它支持任意大数字的移位.这具有简单的优点,但缺点是不填充到原始字节数组大小,即输入可能是16字节但输出可能只有10等,需要额外的逻辑.

BigInteger方法

byte [] array = new byte[]{0x7F,0x11,0x22,0x33,0x44,0x55,0x66,0x77};

// create from array
BigInteger bigInt = new BigInteger(array);

// shift
BigInteger shiftInt = bigInt.shiftRight(4);

// back to array
byte [] shifted = shiftInt.toByteArray();

// print it as hex
for (byte b : shifted) {
    System.out.print(String.format("%x", b));
}
Run Code Online (Sandbox Code Playgroud)

产量

7f1122334455667   <== shifted 4 to the right. Looks OK
Run Code Online (Sandbox Code Playgroud)

长期操纵

我不知道你为什么要这样做,因为这会让生活变得更加困难,你必须在K1等左侧出现的位置留空.你使用shift会更好IMO如下所述.我使用了20的移位可被4整除,因此更容易看到输出中的半字节移动.

1)使用ByteBuffer从16字节数组形成两个长整数

byte[] array = { 0x00, 0x00, 0x11, 0x11, 0x22, 0x22, 0x33, 0x33, 0x44, 0x44, 0x55, 0x55, 0x66, 0x66, 0x77, 0x77 };
ByteBuffer buffer = ByteBuffer.wrap(array);
long k1 = buffer.getLong();
long k2 = buffer.getLong();
Run Code Online (Sandbox Code Playgroud)

2)将每个长n位向右移位

int n = 20;

long k1Shift = k1 >> n;
long k2Shift = k2 >> n;

System.out.println(String.format("%016x => %016x", k1, k1Shift));
System.out.println(String.format("%016x => %016x", k2, k2Shift));

0000111122223333 => 0000000001111222
4444555566667777 => 0000044445555666
Run Code Online (Sandbox Code Playgroud)

从k1确定"被推离边缘"的位

long k1CarryBits = (k1 << (64 - n));
System.out.println(String.format("%016x => %016x", k1, k1CarryBits));

0000111122223333 => 2333300000000000
Run Code Online (Sandbox Code Playgroud)

将K1进位加入右侧的K2

long k2WithCarray = k2Shift | k1CarryBits;
System.out.println(String.format("%016x => %016x", k2Shift, k2WithCarray));

0000044445555666 => 2333344445555666
Run Code Online (Sandbox Code Playgroud)

将两个long写回ByteBuffer并提取为字节数组

buffer.position(0);
buffer.putLong(k1Shift);
buffer.putLong(k2WithCarray);
for (byte each : buffer.array()) {
    System.out.print(Long.toHexString(each));
}

000011112222333344445555666
Run Code Online (Sandbox Code Playgroud)