Java通過導出超大Excel文件解決內存溢出問題
前言
將業(yè)務數(shù)據(jù)導出到Excel表中,導出任務數(shù)據(jù)量較大時,導出的項目就會內存溢出,本文通過Java操作Poi的SXSSFWorkbook類進行導出,解決內存溢出問題。
1.采用Poi中的SXSSFWorkbook
在實現(xiàn)excel導出時,在數(shù)據(jù)量過大的情況下,總是容易發(fā)生內存溢出的情況??梢允褂肞OI提供的 SXSSFWorkbook 類來避免內存溢出。
2.maven中引入Poi
<!-- poi start --> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>4.1.2</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>4.1.2</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml-schemas</artifactId> <version>4.1.2</version> </dependency> <!-- poi end -->
3.測試過程
先使用普通的寫法測試(XSSFWorkbook),編寫writeNormalExcelTest測試方法,寫入的行數(shù)太多時,會報內存溢出(在設置-server -Xmx64m -Xms64m -Xmn32m的情況下)。
接著編寫SXSSFWorkbook操作excel的測試,測試方法writeHugeExcelTest(同樣在設置-server -Xmx64m -Xms64m -Xmn32m的情況下),結果證明無內存溢出,能完好的導出1000000行測試數(shù)據(jù),整個Java類代碼如下:
4.單元測試Java代碼
package cn.gzsendi.exceltest; import java.io.FileOutputStream; import java.io.IOException; 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.xssf.streaming.SXSSFWorkbook; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.junit.Test; public class HugeExcelExportTest { private int totalRowNumber = 1000000; //寫入的excel數(shù)據(jù)行數(shù) private int totalCellNumber = 40; //excel每行共40列 //普通的寫入excel的方法,會消耗內存,寫入的行數(shù)太大時,會報內存溢出 @Test public void writeNormalExcelTest(){ Workbook wb = null; FileOutputStream out = null; try { long startTime = System.currentTimeMillis(); wb = new XSSFWorkbook(); Sheet sheet = wb.createSheet("Sheet 1"); //定義Row和Cell變量, Rows從0開始. Row row; Cell cell; for (int rowNumber = 0; rowNumber < totalRowNumber; rowNumber++) { row = sheet.createRow(rowNumber); for (int cellNumber = 0; cellNumber < totalCellNumber; cellNumber++) { cell = row.createCell(cellNumber); cell.setCellValue(Math.random()); //寫入一個隨機數(shù) } //打印測試, if(rowNumber % 10000 ==0) { System.out.println(rowNumber); } } //Write excel to a file out = new FileOutputStream("d:\\temp\\normalExcel_" + totalRowNumber + ".xlsx"); wb.write(out); long endTime = System.currentTimeMillis(); System.out.println("process " + totalRowNumber + " spent time:" + (endTime - startTime) + " ms."); } catch (Exception e) { e.printStackTrace(); } finally { try { if(out != null) out.close(); } catch (IOException e) { e.printStackTrace(); } try { if(wb != null) wb.close(); } catch (IOException e) { e.printStackTrace(); } } } //結合臨時文件壓縮等寫入excel,默認超過100行就寫到臨時文件,不會報內存溢出 @Test public void writeHugeExcelTest(){ SXSSFWorkbook wb = null; FileOutputStream out = null; try { long startTime = System.currentTimeMillis(); wb = new SXSSFWorkbook();//默認100行,超100行將寫入臨時文件 wb.setCompressTempFiles(false); //是否壓縮臨時文件,否則寫入速度更快,但更占磁盤,但程序最后是會將臨時文件刪掉的 Sheet sheet = wb.createSheet("Sheet 1"); //定義Row和Cell變量, Rows從0開始. Row row; Cell cell; for (int rowNumber = 0; rowNumber < totalRowNumber; rowNumber++) { row = sheet.createRow(rowNumber); for (int cellNumber = 0; cellNumber < totalCellNumber; cellNumber++) { cell = row.createCell(cellNumber); cell.setCellValue(Math.random()); //寫入一個隨機數(shù) } //打印測試, if(rowNumber % 10000 ==0) { System.out.println(rowNumber); } } //Write excel to a file out = new FileOutputStream("d:\\temp\\hugeExcel_" + totalRowNumber + ".xlsx"); wb.write(out); long endTime = System.currentTimeMillis(); System.out.println("process " + totalRowNumber + " spent time:" + (endTime - startTime) + " ms."); } catch (Exception ex) { ex.printStackTrace(); } finally { if (wb != null) { wb.dispose();// 刪除臨時文件,很重要,否則磁盤可能會被寫滿 } try { if(out != null) out.close(); } catch (IOException e) { e.printStackTrace(); } try { if(wb != null) wb.close(); } catch (IOException e) { e.printStackTrace(); } } } }
5.結論
導出excel數(shù)據(jù)量大時,采用SXSSFWorkbook進行操作,數(shù)據(jù)達到一定數(shù)據(jù)將寫數(shù)據(jù)到臨時文件,不會一直占用內存,因此不會報內存溢出
到此這篇關于Java通過導出超大Excel文件解決內存溢出問題的文章就介紹到這了,更多相關Java導出超大Excel文件內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
基于Java+SpringBoot實現(xiàn)人臉識別搜索
人臉識別搜索技術作為現(xiàn)代計算機視覺領域的重要研究方向之一,已經在多個領域展現(xiàn)出巨大的應用潛力,隨著信息技術的飛速發(fā)展,人臉識別搜索在多個領域得到了廣泛關注和應用,本文旨在探討人臉識別搜索技術的背景、原理以及其在實際應用中的意義和挑戰(zhàn)2023-08-08Spring Data JPA帶條件分頁查詢實現(xiàn)原理
這篇文章主要介紹了Spring Data JPA帶條件分頁查詢實現(xiàn)原理,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-05-05MyBatis自定義映射關系和關聯(lián)查詢實現(xiàn)方法詳解
這篇文章主要介紹了MyBatis自定義映射關系和關聯(lián)查詢實現(xiàn)方法,當POJO屬性名與數(shù)據(jù)庫列名不一致時,需要自定義實體類和結果集的映射關系,在MyBatis注解開發(fā)中,使用@Results定義并使用自定義映射,使用 @ResultMap使用自定義映射2023-04-04詳解java中Reference的實現(xiàn)與相應的執(zhí)行過程
不知道大家知不知道特殊的reference對象都是被jvm專門處理的,所以這篇文章就相應的工作流程和referencequeue之間的協(xié)作進行梳理.有需要的朋友們可以參考借鑒。2016-09-09