我惊奇地发现,今天我找不到任何简单的方法来用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);
}

当前回答

使用Commons Net的Util类:

import org.apache.commons.net.io.Util;
...
Util.copyStream(in, out);

其他回答

正如Javadoc所指出的那样,PipedInputStream和PipedOutputStream只能在有多个线程时使用。

另外,请注意输入流和输出流不会用ioexception包装任何线程中断…所以,你应该考虑在你的代码中加入中断策略:

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

如果您希望使用这个API复制大量数据,或者从流中复制长时间无法忍受的数据,那么这将是一个有用的补充。

使用Java7和try-with-resources,提供了一个简化且可读的版本。

try(InputStream inputStream = new FileInputStream("C:\\mov.mp4");
    OutputStream outputStream = new FileOutputStream("D:\\mov.mp4")) {

    byte[] buffer = new byte[10*1024];

    for (int length; (length = inputStream.read(buffer)) != -1; ) {
        outputStream.write(buffer, 0, length);
    }
} catch (FileNotFoundException exception) {
    exception.printStackTrace();
} catch (IOException ioException) {
    ioException.printStackTrace();
}

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

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

PipedInputStream和PipedOutputStream可能会有一些用处,因为您可以将其中一个连接到另一个。

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

所以,你有:

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

...在你的代码中。

你为什么要避开ioutil ?