1. 程式人生 > >JavaWEB_POI匯出大量資料excel(50萬左右)

JavaWEB_POI匯出大量資料excel(50萬左右)

POI 對大資料量的匯出是一個難點,這裡博主總結了兩種處理方式:

方式一,使用高版本的POI,具有記憶體自動釋放的特點。

方式二,將資料匯出到多個Excel中,並進行壓縮處理,上傳到伺服器中。

方式一:

POI之前的版本不支援大資料量處理,如果資料過多則經常報OOM錯誤,有時候調整JVM大小效果也不是太好。3.8版本的POI新出來了SXSSFWorkbook,可以支援大資料量的操作,只是SXSSFWorkbook只支援.xlsx格式,不支援.xls格式。

    3.8版本的POI對excel的匯出操作,一般只使用HSSFWorkbook以及SXSSFWorkbook,
HSSFWorkbook用來處理較少的資料量,SXSSFWorkbook用來處理大資料量以及超大資料量的匯出。     HSSFWorkbook的使用方法和之前的版本的使用方法一致,這裡就不在陳述使用方法了     SXSSFWorkbook的使用例子如下:
import junit.framework.Assert;
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.usermodel.Workbook; 
import org.apache.poi.ss.util.CellReference; 
import org.apache.poi.xssf.streaming.SXSSFWorkbook; 
public static void main(String[] args) throws Throwable { 
 Workbook 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 < 100000; 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("/temp/sxssf.xlsx"); 
 wb.write(out); 
 out.close();
以前還用xml來處理,現在3.8以上就好辦了。

方式二:

說明:我的電腦 2.0CPU 2G記憶體 能夠十秒鐘匯出 20W 條資料 ,12.8M的excel內容壓縮後2.68M

我們知道在POI匯出Excel時,資料量大了,很容易導致記憶體溢位。由於Excel 一個sheet允許的最大行數是65536這時我們想到分sheet進行匯出;但是這種情況也不能解決記憶體溢位的問題。畢竟資料還是一次性在記憶體中進行儲存的。這時我們想是不是可以匯出多個excel呢?下面我就嘗試著按照匯出多個excel

首先:我們要確定資料量有多大,然後確定一個excel匯出多少條資料,這樣就可以確定匯出的Excel的數量,於是我們就可以迴圈的匯出excel並儲存在任意的臨時目錄中。去這樣如果記憶體不夠的話虛擬機器就會去進行回收已經儲存的excel在記憶體中的空間。

假設我們我們已經成功的生成了多個excel,這時我們怎麼把這N個excel文件傳到客戶端呢?其實一個一個的傳也未嘗不可,但是考慮那樣對使用者來說體驗不夠好,再次多個檔案在網路上傳輸也比較慢。我們可以考慮對生成的幾個檔案進行壓縮,然後傳到客戶端。

總結一下

第一、分批次生成excel

第二、壓縮後到客戶端

下面我把我的一個小例項貼上供大家參考

第一、Person.java 普通javabean

Javabean程式碼  收藏程式碼
  1. package bean;  
  2. /**  
  3.  *   
  4.  * @author http://javaflex.iteye.com/  
  5.  *  
  6.  */  
  7. public class Person {  
  8.     private Integer id;  
  9.     private String name;  
  10.     private String address;  
  11.     private String tel;  
  12.     private Double money=0.0;  
  13.     public Double getMoney() {  
  14.         return money;  
  15.     }  
  16.     public void setMoney(Double money) {  
  17.         this.money = money;  
  18.     }  
  19.     public Person(Integer id, String name, String address, String tel,Double money) {  
  20.         super();  
  21.         this.id = id;  
  22.         this.name = name;  
  23.         this.address = address;  
  24.         this.tel = tel;  
  25.         this.money=money;  
  26.     }  
  27.     public Integer getId() {  
  28.         return id;  
  29.     }  
  30.     public void setId(Integer id) {  
  31.         this.id = id;  
  32.     }  
  33.     public String getName() {  
  34.         return name;  
  35.     }  
  36.     public void setName(String name) {  
  37.         this.name = name;  
  38.     }  
  39.     public String getAddress() {  
  40.         return address;  
  41.     }  
  42.     public void setAddress(String address) {  
  43.         this.address = address;  
  44.     }  
  45.     public String getTel() {  
  46.         return tel;  
  47.     }  
  48.     public void setTel(String tel) {  
  49.         this.tel = tel;  
  50.     }  
  51. }  

第二、PersonService模擬業務邏輯迴圈生成100023個Person物件

模擬業務邏輯程式碼  收藏程式碼
  1. package service;  
  2. import java.util.ArrayList;  
  3. import java.util.List;  
  4. import bean.Person;  
  5. /**  
  6.  *   
  7.  * @author http://javaflex.iteye.com/  
  8.  *  
  9.  */  
  10. public class PersonService {  
  11.     public static List getPerson(){  
  12.         List<Person> list =new ArrayList<Person>();  
  13.         for(int i=0;i<100320;i++){  
  14.             list.add(new Person(i,"zhangsan"+i,"北京"+i,"13214587632",123123.12+i));    
  15.         }  
  16.         return list;  
  17.     }  
  18. }  

 第三、業務處理Servlet

操作servlet程式碼  收藏程式碼
  1. package servlet;  
  2. import java.io.File;  
  3. import java.io.FileInputStream;  
  4. import java.io.FileOutputStream;  
  5. import java.io.IOException;  
  6. import java.io.OutputStream;  
  7. import java.text.SimpleDateFormat;  
  8. import java.util.ArrayList;  
  9. import java.util.Date;  
  10. import java.util.List;  
  11. import javax.servlet.ServletException;  
  12. import javax.servlet.http.HttpServlet;  
  13. import javax.servlet.http.HttpServletRequest;  
  14. import javax.servlet.http.HttpServletResponse;  
  15. import org.apache.poi.hssf.usermodel.HSSFWorkbook;  
  16. import org.apache.poi.hssf.util.CellRangeAddress;  
  17. import org.apache.poi.ss.usermodel.Cell;  
  18. import org.apache.poi.ss.usermodel.CellStyle;  
  19. import org.apache.poi.ss.usermodel.Row;  
  20. import org.apache.poi.ss.usermodel.Sheet;  
  21. import org.apache.poi.ss.usermodel.Workbook;  
  22. import bean.Person;  
  23. import service.PersonService;  
  24. /**  
  25.  *   
  26.  * @author http://javaflex.iteye.com/  
  27.  *  
  28.  */  
  29. public class PersonServlet extends HttpServlet {  
  30.     private String fileName;  
  31.     public PersonServlet() {  
  32.         super();  
  33.     }  
  34.     public void destroy() {  
  35.         super.destroy(); // Just puts "destroy" string in log  
  36.         // Put your code here  
  37.     }  
  38.     public void doGet(HttpServletRequest request, HttpServletResponse response)  
  39.             throws ServletException, IOException {  
  40.         // 檔名獲取  
  41.         Date date = new Date();  
  42.         SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");  
  43.         String f = "Person-" + format.format(date);  
  44.         this.fileName = f;  
  45.         setResponseHeader(response);  
  46.         OutputStream out = null;  
  47.         try {  
  48.             out = response.getOutputStream();  
  49.             List<Person> list = PersonService.getPerson();  
  50.             toExcel(list,request,10000,f,out);  
  51.         } catch (IOException e1) {  
  52.             e1.printStackTrace();  
  53.         } finally {  
  54.             try {  
  55.                 out.flush();  
  56.                 out.close();  
  57.             } catch (IOException e) {  
  58.                 e.printStackTrace();  
  59.             }  
  60.         }  
  61.     }  
  62.     /** 設定響應頭 */  
  63.     public void setResponseHeader(HttpServletResponse response) {  
  64.         try {  
  65.             response.setContentType("application/octet-stream;charset=UTF-8");  
  66.             response.setHeader("Content-Disposition""attachment;filename="  
  67.                     + java.net.URLEncoder.encode(this.fileName, "UTF-8")  
  68.                     + ".zip");  
  69.             response.addHeader("Pargam""no-cache");  
  70.             response.addHeader("Cache-Control""no-cache");  
  71.         } catch (Exception ex) {  
  72.             ex.printStackTrace();  
  73.         }  
  74.     }  
  75.     public void doPost(HttpServletRequest request, HttpServletResponse response)  
  76.             throws ServletException, IOException {  
  77.         doGet(request, response);  
  78.     }  
  79.     public void init() throws ServletException {  
  80.         // Put your code here  
  81.     }  
  82.     public void toExcel(List<Person> list, HttpServletRequest request,  
  83.             int length, String f, OutputStream out) throws IOException {  
  84.         List<String> fileNames = new ArrayList();// 用於存放生成的檔名稱s  
  85.         File zip = new File(request.getRealPath("/files") + "/" + f + ".zip");// 壓縮檔案  
  86.         // 生成excel  
  87.         for (int j = 0, n = list.size() / length + 1; j < n; j++) {  
  88.             Workbook book = new HSSFWorkbook();  
  89.             Sheet sheet = book.createSheet("person");  
  90.             double d = 0;// 用來統計  
  91.             String file = request.getRealPath("/files") + "/" + f + "-" + j  
  92.                     + ".xls";  
  93.             fileNames.add(file);  
  94.             FileOutputStream o = null;  
  95.             try {  
  96.                 o = new FileOutputStream(file);  
  97.                 // sheet.addMergedRegion(new  
  98.                 // CellRangeAddress(list.size()+1,0,list.size()+5,6));  
  99.                 Row row = sheet.createRow(0);  
  100.                 row.createCell(0).setCellValue("ID");  
  101.                 row.createCell(1).setCellValue("NAME");  
  102.                 row.createCell(2).setCellValue("ADDRESS");  
  103.                 row.createCell(3).setCellValue("TEL");  
  104.                 row.createCell(4).setCellValue("Money");  
  105.                 int m = 1;  
  106.                 for (int i = 1, min = (list.size() - j * length + 1) > (length + 1) ? (length + 1)  
  107.                         : (list.size() - j * length + 1); i < min; i++) {  
  108.                     m++;  
  109.                     Person user = list.get(length * (j) + i - 1);  
  110.                     Double dd = user.getMoney();  
  111.                     if (dd == null) {  
  112.                         dd = 0.0;  
  113.                     }  
  114.                     d += dd;  
  115.                     row = sheet.createRow(i);  
  116.                     row.createCell(0).setCellValue(user.getId());  
  117.                     row.createCell(1).setCellValue(user.getName());  
  118.                     row.createCell(2).setCellValue(user.getAddress());  
  119.                     row.createCell(3).setCellValue(user.getTel());  
  120.                     row.createCell(4).setCellValue(dd);  
  121.                 }  
  122.                 CellStyle cellStyle2 = book.createCellStyle();  
  123.                 cellStyle2.setAlignment(CellStyle.ALIGN_CENTER);  
  124.                 row = sheet.createRow(m);  
  125.                 Cell cell0 = row.createCell(0);  
  126.                 cell0.setCellValue("Total");  
  127.                 cell0.setCellStyle(cellStyle2);  
  128.                 Cell cell4 = row.createCell(4);  
  129.                 cell4.setCellValue(d);  
  130.                 cell4.setCellStyle(cellStyle2);  
  131.                 sheet.addMergedRegion(new CellRangeAddress(m, m, 03));  
  132.             } catch (Exception e) {  
  133.                 e.printStackTrace();  
  134.             }  
  135.             try {  
  136.                 book.write(o);  
  137.             } catch (Exception ex) {  
  138.                 ex.printStackTrace();  
  139.             } finally {  
  140.                 o.flush();  
  141.                 o.close();  
  142.             }  
  143.         }  
  144.         File srcfile[] = new File[fileNames.size()];  
  145.         for (int i = 0, n = fileNames.size(); i < n; i++) {