Java 如何使用 NIO 将 InputStream 写入文件?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16581724/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to use NIO to write InputStream to File?
提问by Tapas Bose
I am using following way to write InputStream
to File
:
我使用下面的方法来写InputStream
到File
:
private void writeToFile(InputStream stream) throws IOException {
String filePath = "C:\Test.jpg";
FileChannel outChannel = new FileOutputStream(filePath).getChannel();
ReadableByteChannel inChannel = Channels.newChannel(stream);
ByteBuffer buffer = ByteBuffer.allocate(1024);
while(true) {
if(inChannel.read(buffer) == -1) {
break;
}
buffer.flip();
outChannel.write(buffer);
buffer.clear();
}
inChannel.close();
outChannel.close();
}
I was wondering if this is the right way to use NIO. I have read a method FileChannel.transferFrom
, which takes three parameter:
我想知道这是否是使用 NIO 的正确方法。我读过一个方法FileChannel.transferFrom
,它需要三个参数:
- ReadableByteChannel src
- long position
- long count
- ReadableByteChannel src
- 多头头寸
- 长数
In my case I only have src
, I don't have the position
and count
, is there any way I can use this method to create the file?
在我的情况下,我只有src
,我没有position
和count
,有什么办法可以使用这种方法来创建文件?
Also for Image is there any better way to create image only from InputStream
and NIO?
同样对于 Image 有没有更好的方法来仅从InputStream
NIO创建图像?
Any information would be very useful to me. There are similar questions here, in SO, but I cannot find any particular solution which suites my case.
任何信息对我都非常有用。这里有类似的问题,在 SO 中,但我找不到任何适合我的情况的特定解决方案。
采纳答案by user207421
No it's not correct. You run the risk of losing data. The canonical NIO copy loop is as follows:
不,这是不正确的。您冒着丢失数据的风险。规范的 NIO 复制循环如下:
while (in.read(buffer) >= 0 || buffer.position() > 0)
{
buffer.flip();
out.write(buffer);
buffer.compact();
}
Note the changed loop conditions, which take care of flushing the output at EOS, and the use of compact()
instead of clear(),
which takes care of the possibility of short writes.
请注意更改的循环条件,它负责在 EOS 上刷新输出,而使用compact()
代替clear(),
则负责短写入的可能性。
Similarly the canonical transferTo()/transferFrom()
loop is as follows:
类似地,规范transferTo()/transferFrom()
循环如下:
long offset = 0;
long quantum = 1024*1024; // or however much you want to transfer at a time
long count;
while ((count = out.transferFrom(in, offset, quantum)) > 0)
{
offset += count;
}
It must be called in a loop, as it isn't guaranteed to transfer the entire quantum.
它必须在循环中调用,因为不能保证传输整个量程。
回答by Evgeniy Dorofeev
I would use Files.copy
我会使用 Files.copy
Files.copy(is, Paths.get(filePath));
as for your version
至于你的版本
ByteBuffer.allocateDirect
is faster - Java will make a best effort to perform native I/O operations directly upon it.Closing is unreliable, if first fails second will never execute. Use try-with-resources instead, Channels are
AutoCloseable
too.
ByteBuffer.allocateDirect
更快 - Java 将尽最大努力直接在其上执行本机 I/O 操作。关闭是不可靠的,如果第一个失败,第二个将永远不会执行。使用 try-with-resources 代替,Channels
AutoCloseable
也是。