【问题标题】:Problems converting byte array to collection of objects将字节数组转换为对象集合的问题
【发布时间】:2022-01-07 09:18:46
【问题描述】:

我正在尝试将输入字节数组转换为另一个数据结构的集合。输入字节数组有很多字节对应于我称之为 Records 的数据结构,其中每个字节由 data (long) 的 8 个字节和 key (double) 的 8 个字节组成记录。我要做的是定义一个自动执行此操作的函数,因为我会非常频繁地执行此过程。这是我现在拥有的功能:

public Record[] bytesToRecord(byte[] byteArray) {
    Record[] arrayRecords = new Record[(byteArray.length/16)];

    for (int i = 0; i <= (byteArray.length); i+=16) {
        arrayRecords[i] = new Record(Arrays.copyOfRange(byteArray, i, i + 16));
    } 
    return arrayRecords;
}

所以正如你在上面看到的,该函数接受一个字节数组,并每隔 16 个字节循环一次以创建一个新的Record 对象并将其附加到arrayRecords,这是Records 中的集合Record 数组。我遇到的问题是我认为出了点问题,所以我的函数不是每条记录正好占用 16 个字节,所以当创建 Record 对象时,我在 Record 类中得到一个 NullPointerException,因为它无法正确切片Record 的 16 字节子数组以获取 datakeylongdouble 值。如下有Record类构造函数:

public class Record {
    private byte[] record;

    long idData = ByteBuffer.wrap(Arrays.copyOfRange(record, 0,9)).getLong();

    double key = ByteBuffer.wrap(Arrays.copyOfRange(record, 9,16)).getDouble();

    public Record(byte[] recordArray) {
        this.record = recordArray;
    }
}

我希望有人可以帮助我修复此功能或建议另一种方法来做我想做的事情。

【问题讨论】:

  • 如果您能提供一些输入数据和预期的输出将会非常有帮助。

标签: java arrays type-conversion


【解决方案1】:

我在您的代码中发现了四个导致代码失败的问题。我将分别介绍它们。

问题 1: 为您提供 NullPointerException 的问题与您的 Record 类有关。当一个新的类实例被创建时,字段在构造函数被执行之前被初始化。这意味着在您的情况下ByteBuffer.wrap(Arrays.copyOfRange(record, 0,9)).getLong();this.record = recordArray; 之前运行。那么问题是第一条语句使用了一个未初始化的数组。

问题 2: 用于指定数组中 double 开头的索引减一。 long 有 8 个字节 0 到 7,其余 8 个字节从 8 到 15 的两倍。给方法的结束索引是 defined,比实际结束索引多 1。

因此,要解决这两个问题,您必须将您的 Record 更改为以下内容:

public class Record {
    long idData;
    double key;

    public Record(byte[] recordArray) {
        this.idData = ByteBuffer.wrap(Arrays.copyOfRange(record, 0,8)).getLong();
        this.key = ByteBuffer.wrap(Arrays.copyOfRange(record, 8,16)).getDouble();
    }
}

问题 3: 在函数 bytesToRecord 中,您有一个 for 循环,从索引 0 开始,直到索引小于或等于数组的长度。必须将其更改为严格更小,否则循环会过于频繁地迭代一次。

问题 4: 您使用循环索引来寻址 Record[]byte[] 中的实体,它们的长度完全不同。最简单的解决方案是遍历Record[] 并计算byte[] 的索引。

这样的事情应该可以解决这两个问题:

public static Record[] bytesToRecord(byte[] byteArray) {
    Record[] arrayRecords = new Record[(byteArray.length/16)];

    for (int i = 0; i < (arrayRecords.length); i++) {
       arrayRecords[i] = new Record(Arrays.copyOfRange(byteArray, i*16, i * 16 + 16));
    }
        
    return arrayRecords;
}

编辑:在我看来,对您的方法的改进是将Record 类限制为仅存储值并在bytesToRecord 内进行所有计算。这样您就不必复制数组的一部分并节省内存。代码应如下所示:

public class Record {
    long idData;
    double key;

    public Record(long idData, double key) {
        this.idData = idData;
        this.key = key;
    }
}
public static Record[] bytesToRecord(byte[] byteArray) {
    Record[] arrayRecords = new Record[(byteArray.length / 16)];

    for (int i = 0; i < (arrayRecords.length); i++) {
        long id = ByteBuffer.wrap(byteArray, i * 16, 8).getLong();
        double key = ByteBuffer.wrap(byteArray, i * 16 + 8, 8).getDouble();

        arrayRecords[i] = new Record(id, key);
    }

   return arrayRecords;
}

【讨论】:

  • 谢谢您,我在此过程中发现了一些东西,但您的解释帮助我改进了代码
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-06-30
  • 1970-01-01
  • 2015-09-24
  • 2021-11-30
  • 2016-02-22
相关资源
最近更新 更多