如何将ByteBuffer的内容放入OutputStream中?

41
我需要将一个java.nio.ByteBuffer的内容放入java.io.OutputStream中。(但是我没有Channel),怎样是最好的方法呢?
我不能使用ByteBuffer的array()方法,因为它可能是只读缓冲区。
我也可能会在使用这个ByteBuffer和一个普通的byte[]数组之间交替写入OutputStream,而这时我可以直接使用OutputStream.write()
1个回答

66

查看Channels.newChannel(OutputStream)方法,它会返回一个基于OutputStream的通道。通过使用WritableByteChannel适配器,你可以提供一个ByteBuffer将其写入OutputStream中。

public void writeBuffer(ByteBuffer buffer, OutputStream stream) {
   WritableByteChannel channel = Channels.newChannel(stream);

   channel.write(buffer);
}

这应该能解决问题!


如果我保留通道和流,我能否同时调用它们? - Jason S
可以的,当然可以,每次创建频道的成本都会降低 :) - ng.
10
请注意,这种方法涉及从ByteBuffer复制到临时数组,然后将其写入OutputStream。如果性能很重要,您可能需要进行一些重构以避免不必要的块拷贝。 - Trevor Robinson
@trevor-robinson,您能详细说明一下您的评论吗?为什么需要复制?如何避免它? - Frederik
7
@Frederik,“OutputStream”本身只接受字节数组,而且由于“ByteBuffer.array()”可能不被支持,因此通常只有通过复制才能实现。作为一个特殊情况,Oracle/OpenJDK的“Channels.newChannel”实现确实会检查流是否(恰好)是“FileOutputStream”,它具有真正的本地通道;否则,它会返回一个适配器(“Channels.WritableByteChannelImpl”),该适配器将缓冲区中的内容以最多8KB的块大小复制到数组中。避免这种情况的唯一方法是贯穿使用通道。您必须架构NIO以获得性能优势。 - Trevor Robinson
当你使用 java.net.http.WebSocket 时,不得不穿过这些环路真是一件遗憾的事情。其中数据以 ByteBuffer 块的形式传递,你必须将它们连接在一起才能实现任何有用的操作。这些字节缓冲区包含一个较大的带偏移量的数组,因此在这种情况下你必须小心谨慎。 - Mark Jeronimus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接