如何将整个输入流读到字节数组?


当前回答

Java 8方式(感谢BufferedReader和Adam Bien)

private static byte[] readFully(InputStream input) throws IOException {
    try (BufferedReader buffer = new BufferedReader(new InputStreamReader(input))) {
        return buffer.lines().collect(Collectors.joining("\n")).getBytes(<charset_can_be_specified>);
    }
}

注意,这个解决方案删除回车符('\r'),可能是不合适的。

其他回答

20年后,终于有了一个不需要第三方库的简单解决方案,这要感谢Java 9:

InputStream is;
…
byte[] array = is.readAllBytes();

还要注意方便的方法readNBytes(byte[] b, int off, int len)和transferTo(OutputStream)来解决重复的需求。

Java 7及以上版本:

import sun.misc.IOUtils;
...
InputStream in = ...;
byte[] buf = IOUtils.readFully(in, -1, false);

您需要从InputStream中读取每个字节,并将其写入ByteArrayOutputStream。

然后你可以通过调用toByteArray()来检索底层的字节数组:

InputStream is = ...
ByteArrayOutputStream buffer = new ByteArrayOutputStream();

int nRead;
byte[] data = new byte[16384];

while ((nRead = is.read(data, 0, data.length)) != -1) {
  buffer.write(data, 0, nRead);
}

return buffer.toByteArray();

您可以使用Apache Commons IO来处理这个任务和类似的任务。

IOUtils类型有一个静态方法来读取InputStream并返回一个字节[]。

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

这将在内部创建一个ByteArrayOutputStream并将字节复制到输出,然后调用toByteArray()。它通过以4KiB为块复制字节来处理大文件。

请参阅InputStream.available()文档:

It is particularly important to realize that you must not use this method to size a container and assume that you can read the entirety of the stream without needing to resize the container. Such callers should probably write everything they read to a ByteArrayOutputStream and convert that to a byte array. Alternatively, if you're reading from a file, File.length returns the current length of the file (though assuming the file's length can't change may be incorrect, reading a file is inherently racy).