区别
用JavaPOI导出Excel时,我们需要考虑到Excel版本及数据量的问题。针对不同的Excel版本,要采用不同的工具类,如果使用错了,会出现错误信息。
HSSFWorkbook:
- poi导出excel最常用的方式
- 操作Excel2003以前(包括2003)的版本,扩展名是.xls
- 导出的行数至多为65535行,超出65536条后系统就会报错。此方式因为行数不足七万行所以一般不会发生内存不足的情况(OOM)
XSSFWorkbook:
- 操作Excel2007的版本,扩展名是.xlsx
- 这种形式的出现是为了突破HSSFWorkbook的65535行局限。其对应的是excel2007(1048576行,16384列)扩展名为“.xlsx”,最多可以导出104万行,不过这样就伴随着一个问题—OOM内存溢出,原因是你所创建的book
sheet row cell等此时是存在内存的并没有持久化。
SXSSFWorkbook
- 从POI 3.8版本开始,提供了一种基于XSSF的低内存占用的SXSSF方式。对于大型excel文件的创建,一个关键问题就是,要确保不会内存溢出。其实,就算生成很小的excel(比如几Mb),它用掉的内存是远大于excel文件实际的size的。如果单元格还有各种格式(比如,加粗,背景标红之类的),那它占用的内存就更多了。对于大型excel的创建且不会内存溢出的,就只有SXSSFWorkbook了。它的原理很简单,用硬盘空间换内存(就像hashmap用空间换时间一样)。
- SXSSFWorkbook是streaming版本的XSSFWorkbook,它只会保存最新的excelrows在内存里供查看,在此之前的excelrows都会被写入到硬盘里(Windows电脑的话,是写入到C盘根目录下的temp文件夹)。被写入到硬盘里的rows是不可见的/不可访问的。只有还保存在内存里的才可以被访问到。当数据量超出65536条后,
当数据量超出65536条后,在使用HSSFWorkbook或XSSFWorkbook,程序会报OutOfMemoryError:Javaheap space;内存溢出错误。这时应该用SXSSFworkbook。
SXSSF Beta 3.8下临时文件删除方法"
注意:针对 SXSSF Beta 3.8下,会有临时文件产生,比如:
poi-sxssf-sheet4654655121378979321.xml
文件位置:java.io.tmpdir这个环境变量下的位置
Windows 7下是C:\Users\xxxxxAppData\Local\Temp
Linux下是 /var/tmp/
要根据实际情况,看是否删除这些临时文件
HSSFWorkbook-SXSSFWorkbook导出excel文件获取大小记录
偶然发现HSSSFWorkbook 和SXSSFWorkbook workbook对象在执行write方法写入数据到ServletOutputStream(输出流)时 是有点区别的
HSSFWorkbook在write方法执行完的时候并没有关闭流 ,所以我们可以对这个流统计大小来获取导出文件的大小,并且最后需要我们手动关闭
而SXSSFWorkbook的write方法流关闭,write方法执行完之后流就拿不到大小了
HSSFWorkbook可以通过拿到流写入到文件里来获取文件的大小来获取导出excel的大小
如下面这个controller例子:
/**
* 导出文件
* @param request
* @param response
*/
@RequestMapping("/salesQuery/modelSalesAmountFaw/exportExcelMap")
public void exportExcel(HttpServletRequest request,HttpServletResponse response){
Map<String, Object> paramsMap = getPageParams(request);
try {
Workbook wb = modelSalesAmountFawManager.exportExcel(request, paramsMap);
String excelName = null;
String languageType = request.getParameter("languageType");
System.out.println("languageType==="+languageType);
if("EN".equals(languageType)){
excelName = java.net.URLEncoder.encode(moduleNameEn, "UTF-8");
} else{
excelName = java.net.URLEncoder.encode(moduleName, "UTF-8");
}
response.setContentType("application/vnd.ms-excel;charset=utf-8");
SimpleDateFormat dateFormater = new SimpleDateFormat("yyyyMMddHHmmss");
Date date=new Date();
response.setHeader("Content-Disposition", "attachment;filename="+excelName+dateFormater.format(date)+".xls" );
ServletOutputStream out = response.getOutputStream();
wb.write(out);
//先把EXCEL写到临时目录,用来获取文件大小,最后删除
File f = new File(request.getSession().getServletContext().getRealPath("/") + "/demoExcel/demo.xls");
if(!f.exists())
{
f.createNewFile();
}
BufferedOutputStream s = new BufferedOutputStream(new FileOutputStream(f));
wb.write(s);
//关闭流
s.flush();
s.close();
out.flush();
out.close();
//记录导出日志,并删除临时文件
paramsMap.put("exportSize", AppFrameworkUtil.getNum(f.length()/1024, 0));
logManager.updateModuleLog(paramsMap);
f.delete();
} catch (Exception e) {
e.printStackTrace();
}
}
HSSFWorkbook的代码实现
引入Maven坐标
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.9</version>
</dependency>
前端绑定
<a href="./cus/exportXls" class="coolbg">导出Excel</