Apache POI
Apache POI 是用Java编写的免费开源的跨平台的 Java API,它可以创建和维护操作各种符合Office Open XML(OOXML)标准和微软的OLE 2复合文档格式(OLE2)的Java API。
用它可以使用Java读取和创建,修改MS Excel文件.而且,还可以使用Java读取和创建MS Word和MSPowerPoint文件。Apache POI 提供Java操作Excel解决方案(适用于Excel97-2008)。
HSSF and XSSF for Excel Documents
需要以下jar 包
<!-- office文档组件 --> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>3.9</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>3.9</version> </dependency> <dependency> <groupId>org.apache.xmlbeans</groupId> <artifactId>xmlbeans</artifactId> <version>2.4.0</version> </dependency>
一、HSSF:支持 excel97—2003之间的,(.xls)
注意:97—2003excel一个sheet最多65536行。
创建步骤:
1、New Workbook//创建一个工作簿
2、New Sheet//创建一个工作表
3、createRow//创建一个行
4、row.createCell(index)//index是指定哪一列
5、cell.setCellValue(1);//向单元格设置内容
分析:WriteExcelHSSF 的代码
是按照上边步骤执行,最后进行写操作。
测试代码:
1 package yycg.poi; 2 3 import org.apache.poi.hssf.usermodel.HSSFWorkbook; 4 import org.apache.poi.ss.usermodel.Cell; 5 import org.apache.poi.ss.usermodel.Row; 6 import org.apache.poi.ss.usermodel.Sheet; 7 import org.apache.poi.ss.usermodel.Workbook; 8 9 import java.io.FileOutputStream; 10 11 /** 12 * poi测试导出excel文件,数据量大出现内存溢出 13 */ 14 public class WriteExcelHSSF { 15 public static void main(String[] args) throws Exception { 16 //创建一个文件输出 流 17 FileOutputStream out = new FileOutputStream("d:/workbook.xls"); 18 //创建一个工作薄 19 Workbook wb = new HSSFWorkbook(); 20 for (int j = 0; j < 11; j++) { 21 Sheet s = wb.createSheet();//创建一个sheet 22 wb.setSheetName(j, "sheet"+j);//指定sheet的名称 23 //xls文件最大支持65536行 24 for (int rownum = 0; rownum < 65536; rownum++) {//创建行,.xls一个sheet中的行数最大65535 25 //创建一行 26 Row row = s.createRow(rownum); 27 for (int cellnum = 0; cellnum < 10; cellnum++) {//一行创建10个单元格 28 // 在行里边创建单元格 29 Cell cell = row.createCell(cellnum); 30 //向单元格写入数据 31 cell.setCellValue(cellnum); 32 } 33 } 34 } 35 System.out.println("int ......."); 36 wb.write(out);//输出 文件内容 37 38 try { 39 Thread.sleep(2000); 40 }catch (InterruptedException e){ 41 e.printStackTrace(); 42 } 43 out.close(); 44 System.out.println("创建excel文件成功!。。。。。。。。。。。。"); 45 } 46 }
通过执行大数据抛出异常:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
内存溢出
总结:HSSF 在使用将excel数据加载到内容再写磁盘,如果是大数据量操作,会导致内存溢出。
二、XSSF:支持2007以上版本,Excel 2007 OOXML (.xlsx)
excel文件格式是基于是xml存储,这是与03版本最大的区别。
XSSF对HSSF性能更好,对内存消耗不高。
可以解决HSSF操作大数据内存溢出问题。
原理:
在创建XSSFworkbook时需要设置构造函数的参数:
SXSSFWorkbook wb = new SXSSFWorkbook(-1); //设置为-1,关闭自动写入磁盘时机,由手动进行控制
SXSSFWorkbook wb = new SXSSFWorkbook(100); //SXSSF设置100表示,只保持100个记录在内存,超过记录则写入磁盘。
创建workbook的过程和HSSF一样,先后创建workbook、sheet、row、cell
测试代码如下:
package yycg.poi; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.util.CellReference; import org.apache.poi.xssf.streaming.SXSSFSheet; import org.apache.poi.xssf.streaming.SXSSFWorkbook; import java.io.FileOutputStream; public class WriterExcelXSSF1 { public static void main(String[] args) throws Exception{ //创建一个SXSSFWorkbook //关闭自动刷新 SXSSFWorkbook wb = new SXSSFWorkbook(-1); //创建一sheet Sheet sheet = wb.createSheet(); for(int rownum=0;rownum<100000;rownum++){ //创建一个行 Row row = sheet.createRow(rownum); for (int cellnum=0;cellnum<10;cellnum++){ //创建单元格 Cell cell = row.createCell(cellnum); //单元格地址 String adress = new CellReference(cell).formatAsString(); cell.setCellValue(adress);//向单元格中写入数据 } //手动控制行刷新到磁盘的方式 if (rownum%10000==0){//一万行向磁盘写一次 ((SXSSFSheet)sheet).flushRows(100);//保留最后100行并刷新所有其他行 //Thread.sleep(1000); System.out.println("写入...."); // ((SXSSFSheet)sh).flushRows() is a shortcut for ((SXSSFSheet)sh).flushRows(0), // this method flushes all rows } } FileOutputStream out=new FileOutputStream("d:/testxssf.xlsx"); wb.write(out);//将临时文件合并,写入最终文件 out.close(); wb.dispose(); } }
package yycg.poi; import java.io.FileOutputStream; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.util.CellReference; import org.apache.poi.xssf.streaming.SXSSFWorkbook; public class WriteExcelSXSSF2 { public static void main(String[] args) throws Throwable { SXSSFWorkbook wb = new SXSSFWorkbook(100); // keep 100 rows in memory, // exceeding rows will be // flushed to disk Sheet sh = wb.createSheet(); for (int rownum = 0; rownum < 1000; 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:/test2222.xlsx"); wb.write(out); out.close(); // dispose of temporary files backing this workbook on disk wb.dispose(); } }
通过跟踪发现,使用XSSF在导出大数据时,手动控制进行写磁盘,写在了临时文件中,我的电脑是:
(C:UsersThinkpadAppDataLocalTemppoi-sxssf-sheet1910970138657434208.xml 该目录有很多临时文件)
最终待导出完成将临时合并成最终文件写入磁盘。
总结:使用XSSF导出数据,将数据写入内存一部分,超过的则立即写磁盘,所以内存占有量有限不会导致内存溢出。