Java通过导出超大Excel文件解决内存溢出问题
导出excel是咱Java开发的必备技能,下面这篇文章主要给大家介绍了关于Java通过导出超大Excel文件解决内存溢出问题的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考下
前言
将业务数据导出到Excel表中,导出任务数据量较大时,导出的项目就会内存溢出,本文通过Java操作Poi的SXSSFWorkbook类进行导出,解决内存溢出问题。
1.采用Poi中的SXSSFWorkbook
在实现excel导出时,在数据量过大的情况下,总是容易发生内存溢出的情况。可以使用POI提供的 SXSSFWorkbook 类来避免内存溢出。
2.maven中引入Poi
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <!-- 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测试方法,写入的行数太多时,会报内存溢出(在设置-server -Xmx64m -Xms64m -Xmn32m的情况下)。
接着编写SXSSFWorkbook操作excel的测试,测试方法writeHugeExcelTest(同样在设置-server -Xmx64m -Xms64m -Xmn32m的情况下),结果证明无内存溢出,能完好的导出1000000行测试数据,整个Java类代码如下:
4.单元测试Java代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 | 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数据行数 private int totalCellNumber = 40 ; //excel每行共40列 //普通的写入excel的方法,会消耗内存,写入的行数太大时,会报内存溢出 @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()); //写入一个随机数 } //打印测试, 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()); //写入一个随机数 } //打印测试, 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数据量大时,采用SXSSFWorkbook进行操作,数据达到一定数据将写数据到临时文件,不会一直占用内存,因此不会报内存溢出
到此这篇关于Java通过导出超大Excel文件解决内存溢出问题的文章就介绍到这了
原文链接:https://juejin.cn/post/7011020885914025998