我惊奇地发现,今天我找不到任何简单的方法来用Java将InputStream的内容写入OutputStream。显然,编写字节缓冲区代码并不难,但我怀疑我只是缺少了一些可以使我的工作更简单(并且代码更清晰)的东西。

那么,给定一个InputStream in和一个OutputStream out,是否有一种更简单的方法来编写下面的代码?

byte[] buffer = new byte[1024];
int len = in.read(buffer);
while (len != -1) {
    out.write(buffer, 0, len);
    len = in.read(buffer);
}

当前回答

使用Guava的ByteStreams.copy():

ByteStreams.copy(inputStream, outputStream);

其他回答

一个IMHO更小的代码片段(也更狭窄地作用于长度变量):

byte[] buffer = new byte[2048];
for (int n = in.read(buffer); n >= 0; n = in.read(buffer))
    out.write(buffer, 0, n);

顺便说一句,我不明白为什么更多的人不使用for循环,而是选择一段时间使用被一些人视为“糟糕”风格的赋值-测试表达式。

我认为这是可行的,但一定要测试一下……轻微的“改进”,但可能会以可读性为代价。

byte[] buffer = new byte[1024];
int len;
while ((len = in.read(buffer)) != -1) {
    out.write(buffer, 0, len);
}

正如WMR提到的,来自Apache的ioutils有一个叫做copy(InputStream,OutputStream)的方法,它所做的正是您所寻找的。

所以,你有:

InputStream in;
OutputStream out;
IOUtils.copy(in,out);
in.close();
out.close();

...在你的代码中。

你为什么要避开ioutil ?

我认为最好使用一个大的缓冲区,因为大多数文件都大于1024字节。另外,检查读取字节数是否为正也是一个很好的做法。

byte[] buffer = new byte[4096];
int n;
while ((n = in.read(buffer)) > 0) {
    out.write(buffer, 0, n);
}
out.close();

JDK使用相同的代码,因此似乎没有“更简单”的方法,没有笨重的第三方库(可能不会做任何不同的事情)。下面是直接从java.nio.file.Files.java中复制的:

// buffer size used for reading and writing
private static final int BUFFER_SIZE = 8192;

/**
  * Reads all bytes from an input stream and writes them to an output stream.
  */
private static long copy(InputStream source, OutputStream sink) throws IOException {
    long nread = 0L;
    byte[] buf = new byte[BUFFER_SIZE];
    int n;
    while ((n = source.read(buf)) > 0) {
        sink.write(buf, 0, n);
        nread += n;
    }
    return nread;
}