15

我正在尝试将 a “清理”ByteBuffer为全零字节(全部0x00)。我试图遍历缓冲区中的所有位置并将它们设置为0x00,但效率很差。有没有更好的方法来快速清除a ByteBuffer- 类似于什么BitSet.clear()

请注意,ByteBuffer.clear()在这种情况下,这对我来说不是一个合适的解决方案——我必须擦除缓冲区内的所有数据,而不仅仅是将指针重置到开头。

有什么提示吗?

编辑: ByteBuffer 用作哈希表的一部分,它维护哈希表条目的引用。每次需要刷新哈希表时,我都必须重置哈希表条目以供以后插入哈希表。由于哈希表是以随机方式访问的,因此我不能简单地 clear() 字节缓冲区的状态。

4

4 回答 4

10

您是否尝试过使用其中一种ByteBuffer.put(byte[])ByteBuffer.put(ByteBuffer)方法一次写入多个零?然后,您可以使用预先填充零的数组或缓冲区,以 100 或 1000 字节的块或其他任何内容对缓冲区进行迭代。

缺点:这是一个可选操作,因此并非 ByteBuffer 的所有实现都需要提供它...

于 2012-06-25T21:52:56.363 回答
4

对于ByteBuffer提供可选array()方法(其中hasArray()返回true)的实现,您可以使用此方法获取对底层数组的引用,然后使用java.util.Arrays#fill().

于 2012-06-25T23:19:03.237 回答
2

如果ByteBuffer在刷新哈希表后需要一个新的干净的零填充,最简单的方法是删除现有的ByteBuffer并分配一个新的。官方文档没有这么说,但是所有已知的实现都将新缓冲区的内存归零。有关更多信息,请参见http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6535542

于 2012-08-30T07:02:23.493 回答
2

正如 DNA 所提到的,预先填充缓冲液并使用ByteBuffer.put(ByteBuffer)可能是最快的便携方式。如果这不切实际,您可以做这样的事情来利用其中一个Arrays.fillUnsafe.putLong在适用时:

public static void fill(ByteBuffer buf, byte b) {
    if (buf.hasArray()) {
        final int offset = buf.arrayOffset();
        Arrays.fill(buf.array(), offset + buf.position(), offset + buf.limit(), b);
        buf.position(buf.limit());
    } else {
        int remaining = buf.remaining();
        if (UNALIGNED_ACCESS) {
            final int i = (b << 24) | (b << 16) | (b << 8) | b;
            final long l = ((long) i << 32) | i;
            while (remaining >= 8) {
                buf.putLong(l);
                remaining -= 8;
            }
        }
        while (remaining-- > 0) {
            buf.put(b);
        }
    }
}

设置UNALIGNED_ACCESS需要对您的 JRE 实现和平台有所了解。下面是我在使用 JNA 时为 Oracle JRE 设置它的方法(它提供Platform.ARCH了一种方便、规范的方式来访问os.arch系统属性)。

/**
 * Indicates whether the ByteBuffer implementation likely supports unaligned
 * access of multi-byte values on the current platform.
 */
private static final boolean UNALIGNED_ACCESS = Platform.ARCH.startsWith("x86");
于 2017-03-12T22:16:08.103 回答