如何使用NIO将InputStream写入File?

时间:2013-05-16 07:46:29

标签: java image file inputstream nio

我使用以下方式将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();
}

我想知道这是否是使用NIO的正确方法。我读过一个方法FileChannel.transferFrom,它有三个参数:

  1. ReadableByteChannel src
  2. 长位置
  3. 长计数
  4. 在我的情况下,我只有src,我没有positioncount,有什么方法可以使用此方法来创建文件吗?

    同样对于Image,有没有更好的方法来仅从InputStream和NIO创建图像?

    任何信息对我都非常有用。这里有类似的问题,在SO中,但我找不到适合我的特定解决方案。

2 个答案:

答案 0 :(得分:43)

我会使用Files.copy

Files.copy(is, Paths.get(filePath));

至于你的版本

  1. ByteBuffer.allocateDirect更快 - Java将尽最大努力直接执行本机I / O操作。

  2. 关闭是不可靠的,如果第一次失败则第二次永远不会执行。请使用try-with-resources,频道也是AutoCloseable

答案 1 :(得分:7)

不,这不正确。您冒着丢失数据的风险。规范的NIO复制循环如下:

while (in.read(buffer) >= 0 || buffer.position() > 0)
{
  buffer.flip();
  out.write(buffer);
  buffer.compact();
}

注意更改的循环条件,它负责刷新EOS的输出,并使用compact()而不是clear(),来处理短写入的可能性。

类似地,规范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;
}

必须在循环中调用它,因为它不能保证传输整个量子。