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

Java 不关闭FileOutPutStream不会向文件写入任何内容吗?,java,file,fileoutputstream,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);

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

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();
    }
}

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

我相信,给定的
InputStream
OutputStream
安装正确。 添加
os.flush()在末尾。当然,调用方中的两个流也应该关闭


作为替代方案,您可以使用Apache IO utils
org.Apache.commons.IO.IOUtils.copy(InputStream输入,OutputStream输出)

是的,您绝对必须关闭目标文件,以确保从JVM到操作系统的所有缓存都已刷新,并且该文件已准备好供读取器使用

以这种方式复制大文件,代码简洁,但操作效率低下。在博客帖子中考虑升级代码以使用更高效的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);
    }
  }
}
InputStream
OutputStream
的使用示例:

// 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()
中还介绍了一种更简洁的方法,它可以用更少的代码实现同样的效果:

// 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();

文件是在调用此方法之前创建的,因此此处的异常不会阻止文件的创建。无论是否存在问题,您都应该关闭资源。同意。我确实关上了。但我仍然无法理解为什么访问复制的文件时偶尔会抛出异常(问题非常零星)。您是否也可以提供调用方方法?更新了调用函数的问题
flush
作为
close
的一部分自动完成。除非您想在不关闭的情况下刷新,否则无需显式执行此操作。是的,但我看不到调用方方法,因此
flush
应该有助于以后正确关闭资源。谢谢您的回答。我理解翻转和紧凑的重要性。但为什么复制会如此偶然地失败呢?我的意思是这个功能每10000次可能会失败一次。它可能失败的原因是什么?您的读卡器是否与写卡器同步?读者怎么知道作者什么时候完成了?如果它正在监视一个目录中出现的文件,那么您就有一个潜在的争用条件。不,它不在同一个流中,我们将文件写入一个新位置,然后尝试在代码中的某个位置读取它。我想你是对的,这是一个比赛条件。谢谢你抽出时间