如何从 ByteBuffer 中获取连续切片?

Posted

技术标签:

【中文标题】如何从 ByteBuffer 中获取连续切片?【英文标题】:How do you get successive slices out of a ByteBuffer? 【发布时间】:2011-07-04 22:38:22 【问题描述】:

我有一个 ByteBuffer,其中包含一个大文件 (100 MB):

    java.nio.ByteBuffer byteBuffer = ByteBuffer.wrap(multipartFile.getBytes());
    writeChannel.write(byteBuffer);
    writeChannel.closeFinally();

我一次只能合法地向writeChannel 写入 1 MB。

如何对 ByteBuffer 的内容进行切片并一次仅将 1 MB 切片写入writeChannel

【问题讨论】:

为什么?只需编写缓冲区,让系统决定如何将其打包或您要执行的任何操作。 【参考方案1】:

您可以使用ByteBuffer#slice() 获取基本ByteBuffer 实例的重复视图,然后将位置向上移动以显示内容的滑动窗口。或者,如果您不需要将基本缓冲区公开给任何其他消费者,则可以对基本缓冲区执行相同的操作。

您可以通过the single-argument Buffer#position(int) method 更改内容视图的起始位置,并通过Buffer#limit(int) 更改视图的结束位置。只要您注意不要将视图推到底层缓冲区的限制之外,您就可以执行以下操作:

final ByteBuffer view = base.slice();
for (int start = base.position(), end = base.limit(), stride = 1000000;
     start != end;
     start = view.limit())
  consume(view.position(start)
              .limit(start + Math.min(end - start, stride)));

我没有测试它,但它看起来正确。可以重写以避免位置的初始设置,这在此处不是绝对必要的,但它会导致一些重复或更尴尬的第一次特殊情况处理。

我这样保留它是为了保留基本的for循环结构。

【讨论】:

【参考方案2】:

据我所知,writeChannel 上的 write()(我认为它的名称是 SocketChannel 类型)将“尝试向通道写入最多 r 个字节,其中 r 是缓冲区,即 dst.remaining(),此时调用此方法”。 (根据this)

ByteBuffer.remaining()的描述说这个方法会“返回当前位置和限制之间的元素个数。”

所以我的猜测不是你不能写整个 ByteBuffer,而是你的代码应该在 ByteBuffer 对象上调用 flip(),所以它变成:

java.nio.ByteBuffer byteBuffer = ByteBuffer.wrap(multipartFile.getBytes());
byteBuffer.flip();
writeChannel.write(byteBuffer);
writeChannel.closeFinally();

正如Buffer.flip() 中所说:“在一系列通道读取或放置操作之后,调用此方法以准备一系列通道写入或相关获取操作”

【讨论】:

以上是关于如何从 ByteBuffer 中获取连续切片?的主要内容,如果未能解决你的问题,请参考以下文章

如何从 ByteBuffer 中获取已使用的 byte[]

JNA ByteBuffer statvfs

JNI从ByteBuffer获取数据,返回byte[]

切片熊猫数据框以获取不连续的列

如何从多维数组中获取维度(切片)

如何使用 ReadableByteChannel 获取文件内容并将其存储在 byteBuffer 中?