在实际项目中,经常会用到POI3.8来导出excel。而导出excel的时候,会因为残留大量以.xml结尾的文件而导致服务器存储空间急剧增长,最后导致系统挂了。为此,该怎么办呢?
.xml后缀残留文件示例
通过大量的翻阅资料,目前有两种解决方式:
方式1:手动清除临时文件
POI3.8并没有提供方法来清除临时文件,为此,这里可以自己手动进行清除:
package com.jack.shx.MySpringBoot;
import java.io.File;
import java.lang.reflect.Field;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.streaming.SheetDataWriter;
public class SXSSFTempFilesDelete {
/***
* Returns a private attribute of a class
* @param containingClass The class that contains the private attribute to retrieve
* @param fieldToGet the name of the attribute to get
* @return The private attribute
* @throws NoSuchFieldException
* @throws IllegalAccessException
*/
public static Object getPrivateAttribute(
Object containingClass, String fieldToGet)
throws NoSuchFieldException, IllegalAccessException
{
// get the field of the containingClass instance
Field declaredField = containingClass.getClass().getDeclaredField(fieldToGet);
declaredField.setAccessible(true); // access it
Object get = declaredField.get(containingClass); // return it!
return get;
}
/***
* Deletes all temporary files of the SXSSFWorkbook instance
* @param workbook
* @throws NoSuchFieldException
* @throws IllegalAccessException
*/
public static void deleteSXSSFTempFiles(SXSSFWorkbook workbook)
throws NoSuchFieldException, IllegalAccessException {
int numberOfSheets = workbook.getNumberOfSheets();
// iterate through all sheets (each sheet as a temp file)
for (int i = 0; i <= numberOfSheets; i++) {
Sheet sheetAt = workbook.getSheetAt(i);
// delete only if the sheet is written by stream
if (sheetAt instanceof SXSSFSheet) {
SheetDataWriter sdw = (SheetDataWriter) getPrivateAttribute(sheetAt, "_writer");
File f = (File) getPrivateAttribute(sdw, "_fd");
try {
f.delete();
} catch (Exception ex) {
// could not delete the file
}
}
}
}
}
或者
方式2:将POI3.8替换成更高的版本,并利用dispose方法清除临时文件
目前,更高版本的POI已经提供了清除临时文件的方法,具体可以参考官网:http://poi.apache.org/apidocs/org/apache/poi/xssf/streaming/SXSSFWorkbook.html
此时,我们在使用的时候就可以方便的清除临时文件,避免空间爆满了:
/**
* 大数据量导出
* @throws IOException
*/
@Test
public void text2() throws IOException {
XSSFWorkbook xssfWorkbook = new XSSFWorkbook(Thread.currentThread().getContextClassLoader().getResourceAsStream("bigdata.xlsx"));
SXSSFWorkbook wb = new SXSSFWorkbook(xssfWorkbook, 1000); //内存中保留 1000 条数据,以免内存溢出,其余写入 硬盘 专门处理大数据
Sheet sh = wb.getSheetAt(0);
for(int rownum = 1; rownum < 75537; rownum++){
Row row = sh.createRow(rownum);
for(int cellnum = 0; cellnum < 10; cellnum++){
Cell cell = row.createCell(cellnum);
String address = new CellReference(cell).formatAsString();
cell.setCellValue(address);
}
}
FileOutputStream out = new FileOutputStream("D:\\sxssf.xlsx");
wb.write(out);
out.close();
// dispose of temporary files backing this workbook on disk
wb.dispose();
请注意 就这个一句话 wb.dispose();