Bit Twiddling:编码无符号基元

时间:2014-01-27 20:05:02

标签: java bit-manipulation

下面是一个将 unsigned 基元类型编码为字节数组并将编码的字节数组作为十进制字符串返回的类。我从概念上理解encodeIntBigEndian& byteArrayToDecimalString工作。但是,我很欣赏明确:

  
      
  1. val移位((size - i - 1) * Byte.SIZE)的原因/方式如何产生无符号的java字节值。
  2.   
  3. 另外,为什么应用0xff的字节掩码会将字节转换为十进制字符串值。
  4.   
public class BruteForceCoding {
 private static byte byteVal = 101; // one hundred and one
 private static short shortVal = 10001; // ten thousand and one
 private static int intVal = 100000001; // one hundred million and one
 private static long longVal = 1000000000001L;// one trillion and one

 private final static int BSIZE = Byte.SIZE / Byte.SIZE;
 private final static int SSIZE = Short.SIZE / Byte.SIZE;
 private final static int ISIZE = Integer.SIZE / Byte.SIZE;
 private final static int LSIZE = Long.SIZE / Byte.SIZE;

 private final static int BYTEMASK = 0xFF; // 8 bits
 public static String byteArrayToDecimalString(byte[] bArray) {
  StringBuilder rtn = new StringBuilder();
  for (byte b : bArray) {
   rtn.append(b & BYTEMASK).append(" ");
  }
  return rtn.toString();
 }

 public static int encodeIntBigEndian(byte[] dst, long val, int offset, int size) {
  for (int i = 0; i < size; i++) {
   dst[offset++] = (byte) (val >> ((size - i - 1) * Byte.SIZE));
  }
  return offset;
 }

 public static void main(String[] args) {
  byte[] message = new byte[BSIZE + SSIZE + ISIZE + LSIZE];
  // Encode the fields in the target byte array
  int offset = encodeIntBigEndian(message, byteVal, 0, BSIZE);
  offset = encodeIntBigEndian(message, shortVal, offset, SSIZE);
  offset = encodeIntBigEndian(message, intVal, offset, ISIZE);
  encodeIntBigEndian(message, longVal, offset, LSIZE);
  System.out.println("Encoded message: " + byteArrayToDecimalString(message));
 }
}

2 个答案:

答案 0 :(得分:0)

1)它本身并不存在。它的作用是将值向下移动一个字节的单位。但是,当与转换为(byte)并且丢弃高位时,这相当于一个移位和掩码操作,它从值中提取单个字节。

2)它没有。它屏蔽高位,保留值的低8位(一个字节) - 与前一种情况下执行的byte相同的操作。但是,默认情况下,将字节呈现为字符串会生成一个字符串,其中包含表示其二进制值的十进制数字(从0到255),并且在调用.append()时会隐式发生这种情况。

答案 1 :(得分:0)

  

为什么/如何将val移位((size - i - 1) * Byte.SIZE)会产生无符号的java字节值。

没有。 >>sign extending shift,因此它不会更改其左参数的符号。保证非{0}位的>>>产生非负结果,因此可以认为具有无符号输出。

无论哪种方式,只要它被转换为byte,该值就会再次签名,因为Java没有无符号字节类型。

  

另外,为什么应用0xff的字节掩码会将字节转换为十进制字符串值。

没有。

十进制转换发生在

rtn.append(b & BYTEMASK).append(" ")
由于type-promotion

(b & BYTEMASK)的类型为int,并且是[0,256]范围内的值,而StringBuilder.append(int)documented后附加了for (int i = 0; i < size; i++) { dst[offset++] = (byte) (val >> ((size - i - 1) * Byte.SIZE)); } 其参数的十进制表示。


更新:

了解

size

考虑它对4 {/ 1}}的作用,它对应于4字节/ 32位java int

dst[offset  ] = (byte) (val >> 24);  // (byte) 0x??????01 == 0x01
dst[offset+1] = (byte) (val >> 16);  // (byte) 0x????0123 == 0x23
dst[offset+2] = (byte) (val >>  8);  // (byte) 0x??012345 == 0x45
dst[offset+3] = (byte) (val >>  0);  // (byte) 0x01234567 == 0x67

所以给定int 0x01234567它将按顺序放入dst字节0x01 0x23 0x45 0x67