Java InputStream 转换为 ByteBuffer

35

我正在阅读dds纹理,但是一旦构建了jar文件后,我就无法通过urlfile访问这些纹理,必须使用InputStream代替。

因此,我需要知道如何从java.io.InputStream获取java.​nio.ByteBuffer

注:无论通过第三方库还是其他方式,只需确保其可用即可。

4个回答

52

对我来说,在这种情况下最好使用Apache commons-io来处理此类任务。

IOUtils类型有一个静态方法可以读取InputStream并返回byte[]

InputStream is;
byte[] bytes = IOUtils.toByteArray(is);

内部将创建一个ByteArrayOutputStream并将字节复制到输出,然后调用toByteArray()

更新:只要您拥有byte array,如@Peter所指出的,您必须转换为ByteBuffer

ByteBuffer.wrap(bytes)

JAVA 9 更新:如 @saka1029 所述,如果您正在使用 Java 9 或更高版本,可以使用默认的 InputStream API,该 API 现在包含 InputStream::readAllBytes 函数,因此不需要外部库。

InputStream is;
byte[] bytes = is.readAllBytes()

4
然后转换为 ByteBuffer? - elect
8
@elect yes,ByteBuffer.wrap(bytes) - Peter Lawrey
4
可能会 OutOfMemory。 - chen
2
@chen 可能会OOM。这个方法只适用于小文件。这就是为什么人们发明了InputStream API :-) >> 以流的形式读取某些东西(一块一块的)。 - digital_infinity

4

关于什么:

ReadableByteChannel channel = Channels.newChannel(inputStream);
ByteBuffer buffer = ByteBuffer.allocate(bufferSize);

while (channel.read(buffer) != -1) {
  //write buffer

};

你确定 read() 在输入流结束时返回 -1 吗?有时它会返回 0。 - happy_marmoset
1
返回: 已读取的字节数,可能为零,如果通道已到达流的末尾,则为-1 - swepss
如果缓冲区不足以读取整个输入流,则可能会陷入繁忙循环,一遍又一遍地尝试读取0字节。这取决于循环体如何处理缓冲区。例如,如果您只想将所有内容读入缓冲区并返回缓冲区,则缓冲区在循环中不会被清空或翻转。 - swpalmer
@happy_marmoset 当流结束时,它返回-1,如果缓冲区已满或者你正在从一个非就绪的非阻塞SocketChannel读取,则返回0。 - undefined
@swpalmer 这就是compact()的作用。 - undefined
@user207421 是的,我知道。我只是在指出循环体中存在一些假设。例如,“写入缓冲区”这个概念是从哪里来的?原帖中提到正在读取“dds纹理”(不管它们是什么),并且可能需要一次性将流的全部内容保存在内存中。compact()可能不适用。 - undefined

2
不需要第三方库的整洁解决方案是:
ByteBuffer byteBuffer = ByteBuffer.allocate(inputStream.available());
Channels.newChannel(inputStream).read(byteBuffer);

请查看ReadableByteChannel#read(ByteBuffer)


你确定只需要一个 read() 就能读取所有输入流吗? - happy_marmoset
不,这取决于您使用的“InputStream”。如果它具有所有可用字节,则它将起作用。 - James Mudd
1
这不是正确使用 InputStream.available() 的方式,而且 Javadoc 上明确指出了这一点。它不会返回流中的总字节数,并且可能返回零。 - undefined

0
从Java 9开始,有一个方法readAllBytes(在类java.io.InputStream中)返回一个字节数组。你可以将该字节数组传递给[静态]方法wrap(在类java.nio.ByteBuffer中),例如:
public ByteBuffer fromInputStrem(InputStream is) throws IOException {
    return ByteBuffer.wrap(is.readAllBytes());
}

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