不关闭FileOutPutStream不会将任何内容写入文件吗?

时间:2018-11-23 10:01:35

标签: java file fileoutputstream

我有一个将给定输入流写入给定输出流的函数。下面的代码。

static void copyStream(InputStream is, OutputStream os) throws IOException {
    byte[] buffer = new byte[4096];
    int len;
    try {
        while ((len = is.read(buffer)) != -1) {
            os.write(buffer, 0, len);
        }
    }
}    

从此函数调用上述函数

public static void copyFile(File srcFile, File destFile) throws IOException {
    FileInputStream fis = new FileInputStream(srcFile);
    try {
        FileOutputStream fos = new FileOutputStream(destFile);
        try {
            **copyStream**(fis, fos);
        } finally {
            if (fos != null)
                fos.close();
        }
    } finally {
        if (fis != null)
            fis.close();
    }
}

在此功能中,我一次写入4 MB。我使用此功能复制图像。有时,我看到未创建目标文件,因此在尝试读取该文件以进行将来处理时会发生异常。我猜想罪魁祸首是没有关闭资源。我的假设好吗?我的功能可能失败的原因是什么?请帮助

2 个答案:

答案 0 :(得分:0)

我相信,鉴于InputStreamOutputStream已正确安装。 最后添加os.flush();。当然,两个流也应该在调用方中关闭。

或者,您可以使用 Apache IO utils org.apache.commons.io.IOUtils.copy(InputStream input, OutputStream output)

答案 1 :(得分:0)

是的,您绝对必须关闭目标文件,以确保从JVM到操作系统的所有高速缓存均被刷新,并且该文件可供读取器使用。

复制大文件的方式简明扼要,但操作效率低下。考虑升级您的代码,以使用博客文章中documented here的更有效的NIO方法。如果博客消失了,则代码如下:

实用程序类:

public final class ChannelTools {
  public static void fastChannelCopy(final ReadableByteChannel src, final WritableByteChannel dest) throws IOException {
    final ByteBuffer buffer = ByteBuffer.allocateDirect(16 * 1024);
    while (src.read(buffer) != -1) {
      // prepare the buffer to be drained
      buffer.flip();
      // write to the channel, may block
      dest.write(buffer);
      // If partial transfer, shift remainder down
      // If buffer is empty, same as doing clear()
      buffer.compact();
    }
    // EOF will leave buffer in fill state
    buffer.flip();
    // make sure the buffer is fully drained.
    while (buffer.hasRemaining()) {
      dest.write(buffer);
    }
  }
}

InputStreamOutputStream的用法示例:

// allocate the stream ... only for example
final InputStream input = new FileInputStream(inputFile);
final OutputStream output = new FileOutputStream(outputFile);
// get an channel from the stream
final ReadableByteChannel inputChannel = Channels.newChannel(input);
final WriteableByteChannel outputChannel = Channels.newChannel(output);
// copy the channels
ChannelTools.fastChannelCopy(inputChannel, outputChannel);
// closing the channels
inputChannel.close();
outputChannel.close()

Wikipedia中还记录了一种更为简洁的方法,该方法可以用更少的代码实现相同的目的:

// Getting file channels
FileChannel in = new FileInputStream(source).getChannel();
FileChannel out = new FileOutputStream(target).getChannel();

// JavaVM does its best to do this as native I/O operations.
in.transferTo(0, in.size(), out);

// Closing file channels will close corresponding stream objects as well.
out.close();
in.close();