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:\Users\Thinkpad\AppData\Local\Temp\poi-sxssf-sheet1910970138657434208.xml 該目錄有很多臨時文件)
最終待導出完成將臨時合並成最終文件寫入磁盤。
總結:使用XSSF導出數據,將數據寫入內存一部分,超過的則立即寫磁盤,所以內存占有量有限不會導致內存溢出。