java.io.IOException: Stream closed的问题排查
程序员文章站
2024-01-30 11:00:16
...
最近开发“导出数据生成文件”功能时使用到多处OutputStream流操作。
如导出excel文件:
//创建outputStream
response.setContentType("APPLICATION/OCTET-STREAM");
response.setHeader("Content-Disposition",
"attachment;filename=" + URLEncoder.encode(zipName.concat(".zip"), "UTF-8"));
outputStream = response.getOutputStream();
//写入
wb.write(outputStream);
outputStream.flush();
如导出zip文件:
//创建zipOutputStream
public static void setZipOutputStream(HttpServletResponse response, String zipName) throws IOException {
response.setContentType("APPLICATION/OCTET-STREAM");
response.setHeader("Content-Disposition",
"attachment;filename=" + URLEncoder.encode(zipName.concat(".zip"), "UTF-8"));
outputStream = new ZipOutputStream(response.getOutputStream());
}
//excel压缩到zip
public static void excelToZipEntry(SXSSFWorkbook workbook, String excelName) throws IOException {
File tmpFile = TempFile.createTempFile("poi-sxssf-template", ".xlsx");
boolean deleted;
try (FileOutputStream os = new FileOutputStream(tmpFile);
FileInputStream fileInputStream = new FileInputStream(tmpFile);
BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream)) {
workbook.write(os);
ZipEntry entry = new ZipEntry(excelName + ".xlsx");
outputStream.putNextEntry(entry);
byte[] buffer = new byte[1024];
int len;
while ((len = bufferedInputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, len);
}
} finally {
outputStream.closeEntry();
deleted = tmpFile.delete();
if (!deleted) {
throw new IOException("Could not delete temporary file after processing: " + tmpFile);
}
}
}
//压缩pdf到zip
public static void pdfToZipEntry(String pdfFileName, byte[] bytes) throws IOException {
try (ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes)) {
ZipEntry entry = new ZipEntry(pdfFileName + ".pdf");
outputStream.putNextEntry(entry);
byte[] buffer = new byte[1024];
int len;
while ((len = byteArrayInputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, len);
}
} finally {
outputStream.closeEntry();
}
}
经常会遇到的异常就是:
java.io.IOException: Stream closed
原因在于:
每次往流里写数据的源代码里,都会检查一下流是否关闭,关闭就抛 java.io.IOException: Stream closed
虽然知道这个异常的意思,但是在找关闭outputstream的原因的时候,还是花费了一些时间。
例如:
在ZipFileUtil是一个生成zip文件的工具类。
ZipFileUtil.class里创建了一个全局唯一的OutputStream,但是在创建的时候,却使用了如下方式创建:
public class ZipFileUtil {
private static ZipOutputStream outputStream;
private static File file;
public static void setZipOutputStream(String filePath) {
file = new File(filePath);
try (FileOutputStream fileOutputStream = new FileOutputStream(file)) {
outputStream = new ZipOutputStream(fileOutputStream);
} catch (Exception e) {
log.error("创建ZipOutputStream失败,filePath={}", filePath, e);
}
outputStream = new ZipOutputStream(fileOutputStream);
}
}
try-catch的方式创建流,在try-catch代码结束的时候会自动关闭OutputStream,
所以在后续插入数据的时候,直接抛出了java.io.IOException: Stream closed
修改方案:
public static void setZipOutputStream(String filePath) {
file = new File(filePath);
try {
fileOutputStream = new FileOutputStream(file);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
outputStream = new ZipOutputStream(fileOutputStream);
}
推荐阅读
-
java.io.IOException: Stream closed的问题排查
-
解决: java.io.IOException: 打开的文件过多 的问题
-
记一次生产Dubbo线程池耗尽的问题排查处理
-
如何设置Fiddler来拦截Java代码发送的HTTP请求,进行各种问题排查
-
CentOS 7 执行 yum 命令失败问题的排查方法
-
Linux服务器Cache占用过多内存导致系统内存不足问题的排查解决
-
tomcat7.0.26的连接数控制bug的问题排查
-
深入学习Spring Boot排查 @Transactional 引起的 NullPointerException问题
-
深入学习Spring Boot排查 @Transactional 引起的 NullPointerException问题
-
JSP上传图片产生 java.io.IOException: Stream closed异常解决方法