使用 MappedByteBuffer 时出现 IndexOutOfBoundsException

Posted

技术标签:

【中文标题】使用 MappedByteBuffer 时出现 IndexOutOfBoundsException【英文标题】:IndexOutOfBoundsException when use MappedByteBuffer 【发布时间】:2017-07-25 21:38:08 【问题描述】:

我正在考虑使用 MappedByteBuffer 将一些数据存储/加载到文件中。假设我有 long 类型的字段 A 和字符串的字段 B 在序列化时如下所示: A(长) | B(字符串)

现在我想写和读它。这是一段示例代码:

RandomAccessFile file = new RandomAccessFile(dataPath.toString(), "rw");
    MappedByteBuffer mbb = file.getChannel().map(FileChannel.MapMode
            .READ_WRITE, 0, 256);
    long num = 500;
    mbb.putLong(0, num); // (1) first write the long value at beginning
    String str = "Hello World!";
    byte[] input = str.getBytes();
    //then write a string
    mbb.put(input, 8, input.length); // (2) IndexOutOfBoundsException

所以以后我可以通过调用mbb.getLong(0)来检索 long 和mbb.get(outputArray,8,outputArray.length)

但现在我在地方 (2) 失败了。有什么建议吗?

【问题讨论】:

你必须输入0 而不是0,因为你的字节数组从零开始 另请注意:您将无法在阅读时使用outputArray.length - 您不知道要分配多少 @IlyaBursov 谢谢!对于您的第一点...这是因为我希望字符串成为从 pos 8 开始的第二个字段。对于第二点,我可以指定 MAX_LEN 的上限,我知道我的字符串不会长于那个并且读入那个缓冲区? put 的第二个参数在源数组中偏移,而不是在目标缓冲区中 @IlyaBursov 我明白了。谢谢。那么在指定位置将字节数组(src)放入当前缓冲区(dst)的建议方法是什么?总是必须调用 mbb.position(index) 来设置它,比如在 8? 【参考方案1】:

试试

mbb.put(destArray, 0, sourceArray.length)

我认为您不想从 8 字节偏移量开始写入,否则您会尝试在数组的长度上写入 8 个字节。

【讨论】:

感谢您的回复。但我打算保留一个映射到文件的 long, string 结构。即我总是在 pos 8 检索字符串。我错过了什么吗? 假设您有一个长度为 10 的数组,当您尝试从偏移量 8 开始写入 10 个字节 (array.length) 时会发生什么?在超出范围之前您只有 2 个字节。 谢谢先生。现在我明白你的意思了。您的意思是说偏移量是针对 src 字节数组(代码中的 outputArray 和我的情况下的输入)? 我更新了答案,偏移量是您开始写入目标数组的位置。 另外,请注意,当您在示例中说 byte[] input = str.getBytes(); 时,您正在创建大小为 12 的数组....所以当您从偏移量 8 开始写入时,您只有 4 个字节才能出去界限。

以上是关于使用 MappedByteBuffer 时出现 IndexOutOfBoundsException的主要内容,如果未能解决你的问题,请参考以下文章

当我在 C++ 中使用结构创建节点时出现分段错误

在 stm32f769i-Discovery 上使用 BSP 库进行录音时出现问题

使用 glvertex4i 传递网格面索引时出现顶点着色器错误

使用 glvertex4i 传递网格面索引时出现顶点着色器错误

使用 aspnet_regiis -i 时出现“dns server not authoritative for zone”错误

使用Areca ARC-1883i时出现“请从最顶层重新启动”错误