【问题标题】:Parsing Bytes Java Efficiently高效解析字节 Java
【发布时间】:2013-08-02 03:50:11
【问题描述】:

所以我正在解析已知数量的字节。但是,前两个字节代表某个数字,然后下一个代表一个只有一个字节的数字,但接下来的四个字节可能都代表一个很大的数字。除了我的方式之外,有没有更好的方法来解析数据。

    switch (i) {
            //Status
            case 2:
                temp[3] = bytes[i];
                break;
            case 3:
                temp[2] = bytes[i];
                ret.put("Status", byteArrayToInt(temp).toString());
                break;
            //Voltage
            case 4:
                temp[3] = bytes[i];
                break;
            case 5:
                temp[2] = bytes[i];
                ret.put("Voltage", byteArrayToInt(temp).toString());
                break;
            //Lowest Device Signal
            case 6:
                temp[3] = bytes[i];
                break;
            case 7:
                temp[2] = bytes[i];
                ret.put("Lowest Device Signal", byteArrayToInt(temp).toString());
                clearBytes(temp);
                break;

}

我正在遍历字节数组,并且我有一个开关,它知道哪些字节到哪个位置,例如我知道第二个和第三个字节到状态码。所以我把它们组合成一个int。临时字节数组是一个 byte[] temp = new byte[4]。 有更好的方法吗?

【问题讨论】:

  • 您可以按照自己的方式使用临时代码,也可以尝试使用某种通用解析器。如果它没有比上述复杂得多,并且您不会对其进行太多更改,那么上述临时方法可能比找出更通用的方案更容易。
  • i 的值是从 byte[] 本身读取的吗?你能提供一些关于数据结构的额外信息吗?
  • 创建字符串并将其放入 Map 比解析要昂贵得多。可能高达 10 倍。我会担心避免先创建对象或设置地图。

标签: java performance parsing byte


【解决方案1】:

ByteBuffer 可以处理。

byte[] somebytes = { 1, 5, 5, 0, 1, 0, 5 };
ByteBuffer bb = ByteBuffer.wrap(somebytes);
int first = bb.getShort(); //pull off a 16 bit short (1, 5)
int second = bb.get(); //pull off the next byte (5)
int third = bb.getInt(); //pull off the next 32 bit int (0, 1, 0, 5)
System.out.println(first + " " + second + " " + third);

Output
261 5 65541

您还可以使用get(byte[] dst, int offset, int length) 方法提取任意数量的字节,然后将字节数组转换为您需要的任何数据类型。

【讨论】:

  • +1 我会一直读下去,直到你得到所有你希望得到的字节
  • 我没有像以前那样获得正确的价值观......不确定发生了什么。 parsedData.put("Status", status); parsedData.put("Voltage", String.valueOf(buffer.getShort())); parsedData.put("Lowest Device Signal", String.valueOf(buffer.getShort())); parsedData.put("Lowest Device Signal Address", String.valueOf(buffer.get()));
  • 您可能还需要在获取“状态”之前调用一次 buffer.getShort() 来跳过前 2 个字节。回想一下,您的 switch 案例从数组索引 2 开始,而不是 0。
  • 聪明人,这就是问题所在,不过,我前段时间自己想通了。但是很好的选择。
【解决方案2】:

您可以使用 DataInputStream 将多个字节作为 int 或 short 读取。看起来您一次只使用 2 个字节,因此您应该阅读短裤而不是整数(在 Java 中始终是 4 个字节)。

但是在下面的代码示例中,我将使用您的描述“但是,前两个字节代表某个数字,然后下一个代表一个只有一个字节的数字,但接下来的四个可能都代表一个数字”

DataInputStream in = new DataInputStream(new ByteArrayInputStream(bytes));

//the first two bytes represent some number
ret.put("first", Short.toString(in.readShort()));
//next one represents a number that's only one byte
ret.put("second", Byte.toString(in.readByte()));
//next four all represent one number
ret.put("Lowest Device Signal", Integer.toString(in.readInt()));

【讨论】:

  • 我从一个BluetoothSocket读取,有时读取4个字节,有时读取3个字节,我只粘贴了前7个案例。 (共58例)
  • 它仍然可以正常工作,只需在每种情况下调用适当的 readXXX() 方法即可。
  • @user2635648 扩展 DataInputStream 并添加方法 readStatus()、readVoltage() 和最后 readRecord() 或您正在读取的整个数据块
  • 怎么知道只读取 in.readShort() 的前 2 个?
  • readShort() 表示读取 2 个连续字节作为单个值。 readInt() 表示读取 4 个连续字节作为单个值
猜你喜欢
  • 2013-01-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-23
  • 2011-03-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多