我目前正在开发一些网络编程代码(这是我的第一个服务器),并且有一个关于优化特定函数的快速问题,该函数将值作为位写入,然后将它们打包成一个字节。优化此函数的原因是因为它在每个服务器滴答声中被使用数千次,用于打包要发送给多个客户端的数据。
一个示例可能更好地解释函数试图实现的内容:值3可以由两个位表示。在二进制中,它看起来像 00000011
。该函数将把这个二进制值转换成11000000
。当再次调用该函数时,它会知道从第三个最高位(从右边算起第三个/十进制32)开始,并在当前字节中写入至多6位。如果还有剩余的位要写入,则会在新字节上开始。
这样做的目的是为了节省空间,如果您有多个值可以少于一个字节。
我的当前函数如下:
private ByteBuffer out = ByteBuffer.allocate(1024);
private int bitIndex = 0;
/*
* Value: The value to write
* Amount: The number of bits to represent the value in.
*/
public OutputBuffer writeBits(long value, int amount) {
if (bitIndex != 0) {
int remainingBits = 8 - bitIndex;
int bytePos = out.position() - 1;
byte current = out.get(bytePos);
int shiftAmount = amount - remainingBits;
int bitsWritten = amount < remainingBits ? amount : remainingBits;
int clearShiftAmount = 8 - bitsWritten + 56;
byte b;
if (shiftAmount < 0) {
b = (byte) (current | (value << remainingBits - amount));
} else {
//deal with negative values
long temp = (value >> shiftAmount);
temp = (temp << clearShiftAmount);
temp = (byte) (temp >>> clearShiftAmount);
b = (byte) (current | temp);
}
out.put(bytePos,b);
bitIndex = (bitIndex + bitsWritten) % 8;
amount -= bitsWritten;
}
if (amount <= 0) {
return this;
}
bitIndex = amount & 7;
int newAmount = amount - bitIndex;
//newValue should not equal 2047
for (int i = 0; i != newAmount; i += 8) {
writeByte((byte) ((value >> i)), false);
}
if (bitIndex > 0)
writeByte((byte) (value << (8 - bitIndex)), false);
return this;
}
作为一个新手,我认为可能有更有效的方法,比如使用位掩码或某种查找表?有任何想法或引导方向都会很好。谢谢。
111110011
时,你如何知道前两个比特是3
而不是实际上前三个比特被发送为7
? - Jim Garrisonjava.util.BitSet
吗?它可以完成你想要的一切,而无需复杂的编码或自己管理缓冲区。请阅读 Javadoc。 - Jim Garrison11000000
。在下一次写入时,我们将取最后一个字节,并根据剩余的位数将位打包到其中。 - Eladian