如何在Java中表示位字段(并发送它们)
在我当前的项目中,我需要通过网络发送一个包含一些n位字段的解析结构。例如:如何在Java中表示位字段(并发送它们),java,networking,bit-manipulation,Java,Networking,Bit Manipulation,在我当前的项目中,我需要通过网络发送一个包含一些n位字段的解析结构。例如: 协议版本:1字节 messageId:1字节 creationTime:6字节 traceId:3位 可靠性:7位 等等 因此,我创建了一个简单的POJO类来表示解析和解析,但我对这些字段使用什么类型有一些疑问,因为这个决定可能会使解析和解析变得容易,或者有点像噩梦。我必须说,通过网络发送的消息有一个非常具体的大小限制:它不能超过所有字段的总和 我首先考虑对所有内容使用字节,然后使用Message.getBytes(
- 协议版本:1字节
- messageId:1字节
- creationTime:6字节
- traceId:3位
- 可靠性:7位
- 等等
byte resultingByte = short2Byte((short) ((field1 % 128) * 2 + (field2 ? 1 : 0)));
请注意,field1和field2都是短类型。我发现这是在位级别工作最方便的方法。因此,我修改了第一个字段,确保只得到7位,将位向左移动2,因为只需要移动一位。最后,我添加了字段2 short,它可以是1或0。然后,我有一个短的8个不太重要的位所需的值
我创建了商品方法以从short2Byte、Long和其他一些方法转换:
private byte [] to2Bytes(int in) {
ByteBuffer ret = ByteBuffer.allocate(2);
int val = in % 65536;
short s1 = (short) (val / 256);
short s0 = (short) (val % 256);
ret.put(short2Byte(s1));
ret.put(short2Byte(s0));
return ret.array();
}
private byte [] to4Bytes(long in) {
ByteBuffer ret = ByteBuffer.allocate(4);
long div = 4294967296L;
long val = in % div;
int rem = 0;
short s3 = (short) (val / 16777216L);
rem = (int) (val % 16777216L);
short s2 = (short) (rem / 65536);
rem = rem % 65536;
short s1 = (short) (rem / 256);
short s0 = (short) (rem % 256);
ret.put(short2Byte(s3));
ret.put(short2Byte(s2));
ret.put(short2Byte(s1));
ret.put(short2Byte(s0));
return ret.array();
}
private byte [] time2Bytes(Long time) {
ByteBuffer ret = ByteBuffer.allocate(6);
String hex = Long.toHexString(time).toUpperCase();
while (hex.length() < 12) {
hex = "0" + hex;
}
while (hex.length() > 12) {
hex = hex.substring(1);
}
try {
for (int i = 0; i < 6; i++) {
String strByte = "" + hex.charAt(i*2) + hex.charAt(i*2 + 1);
short b = Short.parseShort(strByte, 16);
if (b > 127) {
b -= 256;
}
ret.put((byte) b);
}
}
catch (NumberFormatException e) {
// Exception captured for correctness
e.printStackTrace();
}
return ret.array();
}
private long bytes2time(byte b5, byte b4, byte b3, byte b2, byte b1, byte b0) {
long l5, l4, l3, l2, l1, l0;
l5 = byte2short(b5) * 1099511627776L;
l4 = byte2short(b4) * 4294967296L;
l3 = byte2short(b3) * 16777216L;
l2 = byte2short(b2) * 65536L;
l1 = byte2short(b1) * 256L;
l0 = byte2short(b0) * 1L;
return l5 + l4 + l3 + l2 + l1 + l0;
}
private long bytes2long(byte b3, byte b2, byte b1, byte b0) {
long l3, l2, l1, l0;
l3 = byte2short(b3) * 16777216L;
l2 = byte2short(b2) * 65536L;
l1 = byte2short(b1) * 256L;
l0 = byte2short(b0) * 1L;
return l3 + l2 + l1 + l0;
}
private int bytes2int(byte b1, byte b0) {
return (int)byte2short(b1) * 256 + (int)byte2short(b0);
}
private short byte2short(byte b) {
if (b < 0) {
return (short) (b+256);
}
return (short)b;
}
private byte short2Byte(short s) {
if (s < 128) {
return (byte) s;
}
else {
return (byte) (s-256);
}
}
private byte[]到2字节(int-in){
ByteBuffer ret=ByteBuffer.allocate(2);
int val=in%65536;
短s1=(短)(val/256);
短s0=(短)(val%256);
ret.put(short2Byte(s1));
回输量(短2字节(s0));
返回ret.array();
}
专用字节[]到4字节(长入){
ByteBuffer ret=ByteBuffer.allocate(4);
长div=4294967296L;
长val=单位为%div;
int-rem=0;
短s3=(短)(val/16777216L);
rem=(int)(val%16777216L);
短s2=(短)(rem/65536);
雷姆=雷姆%65536;
短s1=(短)(rem/256);
短s0=(短)(rem%256);
ret.put(short2Byte(s3));
ret.put(short2Byte(s2));
ret.put(short2Byte(s1));
回输量(短2字节(s0));
返回ret.array();
}
专用字节[]时间2字节(长时间){
ByteBuffer ret=ByteBuffer.allocate(6);
字符串hex=Long.toHexString(time).toUpperCase();
while(十六进制长度()<12){
hex=“0”+十六进制;
}
while(十六进制长度()>12){
十六进制=十六进制子串(1);
}
试一试{
对于(int i=0;i<6;i++){
字符串strByte=“”+十六进制字符(i*2)+十六进制字符(i*2+1);
short b=short.parseShort(标准红细胞,16);
如果(b>127){
b-=256;
}
ret.put((字节)b);
}
}
捕获(数字格式){
//为正确性捕获异常
e、 printStackTrace();
}
返回ret.array();
}
专用长字节2时间(字节b5、字节b4、字节b3、字节b2、字节b1、字节b0){
长l5,l4,l3,l2,l1,l0;
l5=字节2短(b5)*109951162776L;
l4=字节2短(b4)*4294967296L;
l3=字节2短(b3)*16777216L;
l2=字节2短(b2)*65536L;
l1=字节2短(b1)*256L;
l0=字节2短(b0)*1L;
返回l5+l4+l3+l2+l1+l0;
}
专用长字节2long(字节b3、字节b2、字节b1、字节b0){
长l3,l2,l1,l0;
l3=字节2短(b3)*16777216L;
l2=字节2短(b2)*65536L;
l1=字节2短(b1)*256L;
l0=字节2短(b0)*1L;
返回l3+l2+l1+l0;
}
专用整型字节2int(字节b1,字节b0){
返回(int)字节短(b1)*256+(int)字节短(b0);
}
专用短字节2短(字节b){
if(b<0){
返回(短)(b+256);
}
返回(短)b;
}
专用字节短2字节(短s){
如果(s<128){
返回(字节)s;
}
否则{
返回(字节)(s-256);
}
}
最后,我将发送一个包含49个字节的字节数组。显然,分离过程非常相似。必须有一个适当的方法来做到这一点,但好吧,它的工作…希望这有助于别人 您可以使用和类来写和读消息,但它仍然可能成为一场噩梦,甚至比纯位操作更糟(这将影响性能)这将是一个问题:“我必须说,通过网络发送的消息有一个非常具体的大小限制:它不能超过所有字段的总和”你在说什么网络协议?我在用UDP包封装消息。我不介意将消息本身打包到几个UDP包中,但是最大消息负载大小是固定的。是的,我在考虑使用位集。我怀疑的是那些字段,比如说6位,我存储在一个字节中。我可以屏蔽我想要的值,但我不确定如何在位的基础上进行迭代,并在位集中添加每个位……我认为您可以为此实现迭代器模式。此外,您还可以实现像“addBits(long source,int count)”这样的方法,以获取“count”低有效位并将其添加到您的位集中。在您的示例中,为什么第一个参数是long?我想知道…我的消息中的大多数元素都是数字的,因此,我可以使用byte、short和int来表示它们,但是对于那些<1字节的元素,我使用byte。有了ByteBuffer,我可以加上一个b