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 utilsorg.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次可能会失败一次。它可能失败的原因是什么?您的读卡器是否与写卡器同步?读者怎么知道作者什么时候完成了?如果它正在监视一个目录中出现的文件,那么您就有一个潜在的争用条件。不,它不在同一个流中,我们将文件写入一个新位置,然后尝试在代码中的某个位置读取它。我想你是对的,这是一个比赛条件。谢谢你抽出时间