我有一个将给定输入流写入给定输出流的函数。下面的代码。
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。我使用此功能复制图像。有时,我看到未创建目标文件,因此在尝试读取该文件以进行将来处理时会发生异常。我猜想罪魁祸首是没有关闭资源。我的假设好吗?我的功能可能失败的原因是什么?请帮助
答案 0 :(得分:0)
我相信,鉴于InputStream
和OutputStream
已正确安装。
最后添加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);
}
}
}
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()
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();