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

时间:2011-07-04 22:38:22

标签: java bytebuffer

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

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

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

如何切片ByteBuffer的内容,一次只将1 MB的切片写入writeChannel

2 个答案:

答案 0 :(得分:10)

您可以使用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 loop 结构。

答案 1 :(得分:0)

据我所知,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()中所说:“在一系列通道读取或放置操作之后,调用此方法来准备一系列通道写入或相对获取操作”

相关问题