快速擦除(不清楚)Java 中的 ByteBuffer

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11197875/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 04:11:25  来源:igfitidea点击:

Fast erase (not clear) a ByteBuffer in Java

javabytebuffererase

提问by asksw0rder

I am trying to "clean up" a ByteBufferto be all zero bytes (all 0x00). I tried to loop over all positions in the buffer and set them to 0x00, but the efficiency is bad. Is there any better way to quickly clear a ByteBuffer- similar to what BitSet.clear()does?

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

Please note that ByteBuffer.clear()is not an appropriate solution for me in this scenario--I have to erase all the data inside of the buffer, and not just reset the pointer to the beginning.

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

Any hints?

任何提示?

Edit: the ByteBuffer is used as a part of the hash table, and it maintains the references of the hash table entries. Every time when the hash table needs to be flushed, I have to reset the hash table entries for later hash table insertion. Since the hash table is accessed in a random-fashion, I cannot simply clear() the state of the byte buffer.

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

采纳答案by DNA

Have you tried using one of the ByteBuffer.put(byte[])or ByteBuffer.put(ByteBuffer)methods to write multiple zeros in one go? You could then iterate over the buffer in chunks of 100 or 1000 bytes, or whatever, using an array or buffer pre-filled with zeros.

您是否尝试过使用ByteBuffer.put(byte[])ByteBuffer.put(ByteBuffer)方法之一一次性写入多个零?然后,您可以使用预先填充零的数组或缓冲区,以 100 或 1000 字节的块或其他任何方式遍历缓冲区。

Downside: this is an optional operation, so not all implementations of ByteBuffer are required to provide it...

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

回答by Jim Garrison

For ByteBufferimplementations that provide the optional array()method (where hasArray()returns true), you could use this method get a reference to the underlying array, then use java.util.Arrays#fill().

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

回答by Trevor Robinson

As DNA mentions, having a pre-filled buffer and using ByteBuffer.put(ByteBuffer)is probably the fastest portable way. If that's not practical, you can do something like this to take advantage of either Arrays.fillor Unsafe.putLongwhen applicable:

正如 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);
        }
    }
}

Setting UNALIGNED_ACCESSrequires some knowledge of your JRE implementation and platform. Here's how I would set it for the Oracle JRE when also using JNA (which provides Platform.ARCHas a convenient, canonical way to access the os.archsystem property).

设置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");

回答by Alex Cohn

If you need a fresh clean zero-filled ByteBufferafter the hash table is flushed, the easiest way is to drop the existing ByteBufferand allocate a new one. The official documentation does not say so, but all known implementations zero the memory of new buffers. See http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6535542for additional info.

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