5

我有一个包含大文件(100 MB)的ByteBuffer :

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

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

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

4

2 回答 2

11

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

您可以通过单参数Buffer#position(int)方法更改内容视图的起始位置,并通过更改视图的结束位置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 循环结构。

于 2011-07-04T23:03:17.667 回答
0

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

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

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

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

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

于 2011-07-04T22:54:24.397 回答