Java多word文件生成后进行压缩并导出下载后,压缩文件损坏并提示“不可预料的压缩文件末端”和“CRC校验失败”
WinRAR 打开情况:
提示不可预料的压缩文件末端,实际情况是两个word文件,但是只显示了一个word文件,并无法打开word文件,提示“压缩文件已损坏”
好压 打开情况:
提示不可预料的压缩文件末端,word文件数量显示正确,并可以正常打开,因为好压自带了压缩文件损坏修复功能,WinRAR则需手动在菜单栏-工具-修复压缩文件进行修复即可正常使用
7-zip 打开情况:
可以打开,文件数量显示正常,可以看到图中第一个word文件的大小为0,此时打开该文件会提示“CRC校验失败”,第二个word文件可以正常打开。
问题分析:
在代码中,把事先生成好的多个文件逐步写入zip中,如果代码中没有编写zip的写入完成状态,那么就会出现此问题,通过图三分析可以推测出,只有一个word大小为0,其他的文件大小是正常的,经过断点调试发现总是最后一个文件压缩后大小显示为0,说明流的关闭完成环节出了问题
解决方案
在多文件写入zip文件,必须增加ZipOutputStream的finish()方法,例如:
(如果只是单个文件,只是用zipOutputStream.close()没有使用zipOutputStream.finish()也没有出现问题)
OutputStream bos = new ByteArrayOutputStream();
ZipOutputStream zipOutputStream = new ZipOutputStream(bos);
ByteArrayOutputStream output = new ByteArrayOutputStream();//ByteArray临时存储流
//此处documentMap是一个hashMap,Key值为文件名称,Value是对应XWPFDocument文件信息
Iterator<Map.Entry<String, XWPFDocument>> docIterator = documentMap.entrySet().iterator();
while (docIterator.hasNext()) {
Map.Entry<String, XWPFDocument> entry = docIterator.next();
XWPFDocument doc = entry.getValue();
String key = entry.getKey();
//如果对应的XWPFDocument文件信息不为空则写入到zip中
if (null != doc) {
//开始写入文件
ZipEntry zipEntry = new ZipEntry(key +".docx");
zipOutputStream.putNextEntry(zipEntry);
output.reset();//重置ByteArray流(为了重复使用)
doc.write(output);//把word对象内容写到ByteArray流临时存储
doc.close();
zipOutputStream.write(output.toByteArray());//把ByteArray流内容写入zip输出流
zipOutputStream.closeEntry();
}
}
output.close();
//结束写入文件
zipOutputStream.finish();