我很惊讶今天发现我无法找到将 InputStream
的内容写入Java中的 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);
}
21 回答
试试Cactoos:
更多细节在这里:http://www.yegor256.com/2017/06/22/object-oriented-input-output-in-cactoos.html
如果您使用的是Java 7,那么Files(在标准库中)是最好的方法:
编辑:当然,从文件创建一个InputStream或OutputStream时它非常有用 . 使用
file.toPath()
从文件中获取路径 .要写入现有文件(例如,使用
File.createTempFile()
创建的文件),您需要传递REPLACE_EXISTING
复制选项(否则抛出FileAlreadyExistsException
):正如WMR所提到的,来自Apache的
org.apache.commons.io.IOUtils
有一个名为copy(InputStream,OutputStream)的方法,它可以完全满足您的需求 .所以你有了:
...在你的代码中 .
你有没有理由避免
IOUtils
?Java 9
从Java 9开始,
InputStream
提供了一个名为transferTo
的方法,其签名如下:正如documentation所述,
transferTo
将:因此,为了将Java
InputStream
的内容写入OutputStream
,您可以编写:我认为这样可行,但一定要测试它......轻微的“改进”,但可读性可能有点费用 .
使用Guava的ByteStreams.copy():
你可以使用这种方法
简单功能
如果您只需要将
InputStream
写入File
,那么您可以使用这个简单的函数:只有在有多个线程时才应使用
PipedInputStream
和PipedOutputStream
,如noted by the Javadoc .另请注意,输入流和输出流不会使用
IOException
包装任何线程中断...因此,您应该考虑在代码中加入中断策略:如果您希望使用此API来复制大量数据,或者将数据从流中陷入无法忍受的长时间,这将是一个有用的补充 .
JDK
使用相同的代码,所以看起来没有"easier"方式没有笨重的第三方库(可能不会做任何不同的事情) . 以下内容直接从java.nio.file.Files.java
复制:对于那些使用 Spring framework 的人来说,有一个有用的StreamUtils类:
以上并没有关闭流 . 如果您希望在复制后关闭流,请使用FileCopyUtils class:
有's no way to do this a lot easier with JDK methods, but as Apocalisp has already noted, you'并不是唯一一个有这个想法的人:你可以使用Jakarta Commons IO来自Jakarta Commons IO,它还有很多其他有用的东西,IMO实际上应该是JDK的一部分......
使用Java7和try-with-resources,附带简化且可读的版本 .
使用Commons Net的Util类:
这就是我如何使用最简单的for循环 .
我认为最好使用大缓冲区,因为大多数文件大于1024字节 . 另外,最好将读取的字节数检查为正数 .
一个恕我直言的更小的片段(也更窄范围长度变量):
作为旁注,我不要使用
for
循环,而是选择带有assign-and-test表达式的while
,该表达式被某些人视为"poor"样式 .PipedInputStream和PipedOutputStream可能有一些用处,因为您可以将一个连接到另一个 .
另一个可能的候选者是Guava I / O实用程序:
http://code.google.com/p/guava-libraries/wiki/IOExplained
我以为我会使用这些,因为Guava在我的项目中已经非常有用,而不是为一个函数添加另一个库 .
我使用
BufferedInputStream
和BufferedOutputStream
从中删除缓冲语义码