java.io.IOException: UT010029: Stream is closed
记录一次项目中的异常,在做下载文件时,文件虽然能够导出来但是系统中却出现了一堆报错信息。java.io.IOException: UT010029: Stream is closed
通过报错信息可以看出这个异常是流被关闭了,在我们学JAVA基础时我们知道,使用I/O流时要及时关闭。但是如果关闭的不合理也是有问题的,这个错误是由于这个流被关闭了,而在其他地方又用到了这个流,所以获取不到流就会报错了。
定位到了大概原因,接下来看下我的功能代码,果然在finally那对输出流进行了关闭处理,由于我对输出流进行了关闭操作,这个流是从response中拿到的,不是自己创建的而我却将他关闭了,Spring MVC框架中可能会使用流进行编码处理等操作,由于拿不到流从而导致的报错。
public static void exportFile(File zipFile, HttpServletResponse response) throws IOException {
// 输入流
BufferedInputStream bufferedInputStream = null;
// 输出流
BufferedOutputStream bufferedOutputStream = null;
try {
response.reset();
//设置文件ContentType类型
response.setContentType("application/json");
//设置Content-Disposition,设置attachment,浏览器会激活文件下载框;filename指定下载后默认保存的文件名
//不设置Content-Disposition的话,文件会在浏览器内打开,比如txt、img文件
response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(zipFile.getName(), "UTF-8"));
// 输入流
bufferedInputStream = new BufferedInputStream(new FileInputStream(zipFile));
// 输出流
bufferedOutputStream = new BufferedOutputStream(response.getOutputStream());
byte[] size = new byte[1024];
int length = 0;
// 2.将文件转换成流,读取到内存中
while ((length = bufferedInputStream.read(size)) != -1) {
bufferedOutputStream.write(size, 0, length);
}
bufferedOutputStream.flush();
} catch (IOException e) {
log.error(e.getMessage());
throw new RuntimeException(Err_000400010061);
} finally {
// 关闭输入流
if (bufferedInputStream != null) {
bufferedInputStream.close();
}
// 使用SpringMVC框架时,在我们的业务代码中处理完业务逻辑后,不要对HttpServletResponse对象的ServletOutputStream做流关闭处理
if (bufferedOutputStream != null) {
bufferedOutputStream.close();
}
}
}
将下面这部分代码去掉后发现报错消失了
// 使用SpringMVC框架时,在我们的业务代码中处理完业务逻辑后,不要对HttpServletResponse对象的ServletOutputStream做流关闭处理
if (bufferedOutputStream != null) {
bufferedOutputStream.close();
}
小结
我们在使用I/O流的原则是,如果是自己手动创建的流,那么我们在使用完后必须将流进行关闭。如果不是自己创建的流,我们不需要也不要手动将流进行关闭,因为框架中可能会用到这些流做一些额外的处理。