使用POI能够导出大数据保证内存不溢出的一个重要原因是SXSSFWorkbook生成的EXCEL为2007版本,修改EXCEL2007文件后缀为ZIP打开可以看到,每一个Sheet都是一个xml文件,单元格格式和单元格坐标均用标签表示。直接使用SXSSFWorkbook来到导出EXCEL本身就是POI为了大数据量导出而量身定制的,所以导出可以直接使用SXSSFWorkbook方式。
为了保险起见可以采用多Sheet的方式保证内存不溢出。需要注意的是Sheet名称不能重复;下载的时候需要定义好返回头。
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
导出EXCEL较为简单,创建Workbook对象和Sheet对象往里塞值就行了。但是导入读取EXCEL的时候SXSSFWorkbook没有读取文件流的方法,只能使用XSSFWorkbook来读取,几千条数据可能就内存溢出了。
这时候就要使用OPCPackage
public static OPCPackage open(java.io.InputStream in) throws InvalidFormatException, java.io.IOException Open a package. Note - uses quite a bit more memory than open(String), which doesn't need to hold the whole zip file in memory, and can take advantage of native methods Parameters: in - The InputStream to read the package from Returns: A PackageBase object Throws: InvalidFormatException java.io.IOException
POI给出的API表示使用OPCPackage不需要将文件完全读取到内存中。
调用方法
File file = uploadFile.getFile(); InputStream is = new FileInputStream(file); excelReader.readInputStream(is); excelReader.process();
ExcelReader.java
/** * 抽象Excel2007读取器,excel2007的底层数据结构是xml文件,采用SAX的事件驱动的方法解析 * xml,需要继承DefaultHandler,在遇到文件内容时,事件会触发,这种做法可以大大降低 * 内存的耗费,特别使用于大数据量的文件。 * */ public class Excel2007Reader extends DefaultHandler { //共享字符串表 private SharedStringsTable sst; //上一次的内容 private String lastContents; private boolean nextIsString;