Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/382.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angular/33.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 从字节数组中获取位值_Java_Bit Manipulation_Bit - Fatal编程技术网

Java 从字节数组中获取位值

Java 从字节数组中获取位值,java,bit-manipulation,bit,Java,Bit Manipulation,Bit,我有一个字节数组,需要从中读取特定的位并转换为int(参见下面的字节数组结构)。尽管我想要读取的位信息是3个字节,但我尝试读取4个字节(6-9)作为整数,然后使用bits或bitsValue方法从该整数值中读取位,但不知何故,我无法从位操作中看到正确的值。以我在bits方面的专业知识,我很肯定我做错了什么。 有人能告诉我我做得对吗?为什么不起作用。提前谢谢 字节数组采用小尾端格式 第0字节-某些值 第1字节-某些值 第2-5字节-某些值 第6-9字节-前18位表示某个值 -接下来的5位代表某个值

我有一个字节数组,需要从中读取特定的位并转换为int(参见下面的字节数组结构)。尽管我想要读取的位信息是3个字节,但我尝试读取4个字节(6-9)作为整数,然后使用bits或bitsValue方法从该整数值中读取位,但不知何故,我无法从位操作中看到正确的值。以我在bits方面的专业知识,我很肯定我做错了什么。 有人能告诉我我做得对吗?为什么不起作用。提前谢谢

字节数组采用小尾端格式

第0字节-某些值 第1字节-某些值 第2-5字节-某些值 第6-9字节-前18位表示某个值 -接下来的5位代表某个值 -下一个1位表示某个值 -最后8位代表某个值

 public class Test {

  public static void main(String... dataProvider) {
    String s = "46 00 ef 30 e9 08 cc a5 03 43";
    byte[] bytes = new byte[s.length()];
    bytes = hexStringToByteArray(s);

    int bytePointer = 0;
    int msgType = getIntFromSingleByte(bytes[bytePointer]); // 0th byte
    int version = getIntFromSingleByte(bytes[++bytePointer]); // 1st byte
    int tickInMS = getIntValue(bytes, ++bytePointer); // 2nd-5th bytes

    bytePointer = bytePointer + 4;
    int headr = getIntValue(bytes, bytePointer); // 6th-9th bytes
    int utcTime = bits(headr, 0, 18); // 6th-9th bytes - 18 bits
    int reserved = bits(headr, 18, 5); // 6th-9th bytes- 5 bits
    int reportOrEvent = bits(headr, 23, 1); // 6th-9th bytes - 1 bits
    int reportId = bitsValue(headr, 24, 32); // 6th-9th- 8 bits

  }



    public static int getIntFromSingleByte(byte data) {
        return (data & 0xFF);
      }

      public static int getIntValue(byte[] bytes, int startPosition) {
        byte[] dest = new byte[4];
        System.arraycopy(bytes, startPosition, dest, 0, dest.length);
        return toInt(dest);
      }

      // took from Stack overflow
      static 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;
      }

      public static int bitsValue(int intNum, int startBitPos, int endBitPos) {
        // parameters checking ignored for now
        int tempValue = intNum << endBitPos;
        return tempValue >> (startBitPos + endBitPos);
      }

      public static byte[] hexStringToByteArray(final String s) {
        String[] splits = s.split(" ");
        final byte[] data = new byte[splits.length];
        for (int i = 0; i < splits.length; i++) {
          char first = splits[i].length() < 2 ? '0' : splits[i].charAt(0);
          char second = splits[i].length() < 2 ? splits[i].charAt(0) : splits[i].charAt(1);
          data[i] = (byte) ((Character.digit(first, 16) << 4) + Character.digit(second, 16));
        }
    return data;
  }

  public static int toInt(byte[] data) {
    if (data == null || data.length != 4)
      return 0x0;

    return (int) ((0xff & data[0]) << 24 | (0xff & data[1]) << 16 | (0xff & data[2]) << 8
        | (0xff & data[3]) << 0);
  }
}
公共类测试{
公共静态void main(字符串…数据提供程序){
字符串s=“46 00 ef 30 e9 08 cc a5 03 43”;
byte[]bytes=新字节[s.length()];
字节=HexstringToByte数组;
int bytePointer=0;
int msgType=getIntFromSingleByte(字节[bytePointer]);//第0字节
int version=getIntFromSingleByte(字节[++bytePointer]);//第1字节
int tickInMS=getIntValue(字节,++bytePointer);//第2-5字节
bytePointer=bytePointer+4;
int headr=getIntValue(字节,bytePointer);//第6-9个字节
int utcTime=位(头,0,18);//第6-9字节-18位
int reserved=位(头,18,5);//第6-9个字节-5位
int reportOrEvent=位(headr,23,1);//第6-9字节-1位
int reportId=bitsValue(headl,24,32);//第6-9-8位
}
公共静态int getIntFromSingleByte(字节数据){
返回(数据和0xFF);
}
公共静态int getIntValue(字节[]字节,int起始位置){
字节[]dest=新字节[4];
System.arraycopy(字节、起始位置、目标、0、目标长度);
返回目的地;
}
//从堆栈溢出中提取
静态整数位(整数n、整数偏移量、整数长度){
//将位向右移动,使所需的块位于右端
n=n>>(31-偏移量-长度);
//准备一个只有最右边的“长度”位为1的掩码
整数掩码=~-1(起始位+结束位);
}
公共静态字节[]hexStringToByteArray(最终字符串s){
字符串[]splits=s.split(“”);
最终字节[]数据=新字节[splits.length];
对于(int i=0;i数据[i]=(字节)((Character.digit(first,16)而不是容易出错的位管理您应该使用数字的二进制字符串表示,并作为字符串操作执行“位选择”:

String s = "46 00 ef 30 e9 08 cc a5 03 43";
String[] hexNumbers = s.split(" ");
for(String hexNumber : hexNumbers) {
  String binaryNumber = String.format("%8s", new BigInteger(hexNumber,16).toString(2)).replace(' ','0');
  System.out.print(String.format("value in hex : %s, value in binary: %s",  hexNumber,binaryNumber));
}

将输入数据包装在
ByteBuffer
中将简化解析,并允许您根据需要调整endianness

您的
bits
方法错误。常量31应为32。此外,该方法使用MSB 0位编号,这对于小端数据来说是奇数。您应该确认您的输入是使用此位编号方案记录的

您的
bitsValue
方法也有错误。在修复后,不妨使用
bits

此代码更简单,可以正确提取位字段:

public static void main(String... args) {
    String s = "46 0 79 37 a8 3 9f 37 1 43 eb 7a f 3 3 fe c4 1 c5 4 c5 5e";
    byte[] input = hexStringToByteArray(s);

    // Wrap the input in a ByteBuffer for parsing. Adjust endianness if necessary.
    ByteBuffer buffer = ByteBuffer.wrap(input).order(ByteOrder.BIG_ENDIAN);

    int msgType = buffer.get() & 0xff;
    int version = buffer.get() & 0xff;
    int tickInMS = buffer.getInt();
    int header = buffer.getInt();

    int utcTime = bits(header, 0, 18);          // 6th-9th bytes - 18 bits
    int reserved = bits(header, 18, 5);         // 6th-9th bytes - 5 bits
    int reportOrEvent = bits(header, 23, 1);    // 6th-9th bytes - 1 bit
    int reportId = bits(header, 24, 8);         // 6th-9th bytes - 8 bits

    System.out.printf("utc: %d, report? %d, id: %d\n", utcTime, reportOrEvent, reportId);
}

/**
 * Extract a bit field from an int. Bit numbering is MSB 0.
 */
public static int bits(int n, int offset, int length) {
    return n >> (32 - offset - length) & ~(-1 << length);
}
publicstaticvoidmain(字符串…参数){
字符串s=“46 0 79 37 a8 3 9f 37 1 43 eb 7a f 3 fe c4 1 c5 4 c5 5e”;
字节[]输入=HexstringToByte数组;
//将输入包装在ByteBuffer中进行分析。如有必要,请调整endianness。
ByteBuffer buffer=ByteBuffer.wrap(输入).order(ByteOrder.BIG_ENDIAN);
int msgType=buffer.get()&0xff;
int version=buffer.get()&0xff;
int tickInMS=buffer.getInt();
int header=buffer.getInt();
int utcTime=位(头,0,18);//第6-9字节-18位
int reserved=位(头,18,5);//第6-9字节-5位
int reportOrEvent=位(头,23,1);//第6-9字节-1位
int reportId=位(头,24,8);//第6-9字节-8位
System.out.printf(“utc:%d,报告?%d,id:%d\n”,utcTime,reportOrEvent,reportId);
}
/**
*从整数中提取位字段。位编号为MSB 0。
*/
公共静态整数位(整数n、整数偏移量、整数长度){

return n>>(32-offset-length)和-1个十六进制数正在运行测试用例。在生产系统中,我需要处理实际字节。我不想添加额外的步骤来转换十六进制数并在其中进行操作。即使在这种情况下,我也不确定我是否理解如何从3个十六进制数(3个字节)中读取18/5/1位你测试了吗?%s在我的Oracle java 8和更早的时候为我投出了0个标志,而javADoc对于<代码>格式化程序< /C> >不适用于“s”的类别“一般”。(这与C++和C++不同,其中0个标志可以应用于任何转换。)这是样本i使用的“46 0 79 37 37 3 9F 37 1 43 EB 7A f 43 FE C4×C5×C5 5E”位。(eb)应该是235,但当我通过逻辑传递它时,它给了我-21,但在你的示例中,你没有读取字节11(它在10处停止)。