Java通过导出超大Excel文件解决内存溢出问题

前言

将业务数据导出到Excel表中,导出任务数据量较大时,导出的项目就会内存溢出,本文通过Java操作Poi的SXSSFWorkbook类进行导出,解决内存溢出问题。

1.采用Poi中的SXSSFWorkbook

在实现excel导出时,在数据量过大的情况下,总是容易发生内存溢出的情况。可以使用POI提供的 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测试方法,写入的行数太多时,会报内存溢出(在设置-server -Xmx64m -Xms64m -Xmn32m的情况下)。

接着编写SXSSFWorkbook操作excel的测试,测试方法writeHugeExcelTest(同样在设置-server -Xmx64m -Xms64m -Xmn32m的情况下),结果证明无内存溢出,能完好的导出1000000行测试数据,整个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数据行数
	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文件解决内存溢出问题的文章就介绍到这了,更多相关Java导出超大Excel文件内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • java导出数据库的全部表到excel

    本文实例为大家分享了java将某个数据库的表全部导出到excel中的方法,供大家参考,具体内容如下 第一步:如何用POI操作Excel @Test public void createXls() throws Exception{ //声明一个工作薄 HSSFWorkbook wb = new HSSFWorkbook(); //声明表 HSSFSheet sheet = wb.createSheet("第一个表"); //声明行 HSSFRow row = sheet.createR

  • java导出大批量(百万以上)数据的excel文件

    本文实例为大家分享了java导出百万以上数据的excel文件,供大家参考,具体内容如下 1.传统的导出方式会消耗大量的内存,2003每个sheet页最多65536条数据,2007每个sheet页可以达到100万条数据以上,2007会在生成Workbook时清理数据,所以2007导出量更大; 2.可以导出多个excel文件到某个目录中,然后打包下载; 3.导出excel格式的xml文件,这种方式可以分批导出数据,适用于大批量数据的导出,以下简单介绍这种方式: 代码如下: package com.e

  • Java根据模板导出Excel报表并复制模板生成多个Sheet页

    因为最近用报表导出比较多,所有就提成了一个工具类,本工具类使用的场景为  根据提供的模板来导出Excel报表 并且可根据提供的模板Sheet页进行复制 从而实现多个Sheet页的需求, 使用本工具类时,如果需求是每个Sheet页中的数据都不一致,但是表格样式和模板都一样 那么只需要在实际情况中根据 sql 来查询要添加的数据源 (只需更改数据源即可) 采用的技术为 POI 导出,因为类的缘故,目前只支持2003版本的Excel. 使用前请先下载相应jar包! 后期有时间的话会进行进一步完善,初次

  • java导出Excel文件的步骤全纪录

    一.背景 当前B/S模式已成为应用开发的主流,而在企业办公系统中,常常有客户这样子要求:你要把我们的报表直接用Excel打开(电信系统.银行系统).或者是:我们已经习惯用Excel打印.这样在我们实际的开发中,很多时候需要实现导入.导出Excel的应用. 最近在java上做了一个EXCEL的导出功能,写了一个通用类,在这里分享分享,该类支持多sheet,且无需手动进行复杂的类型转换,只需提供三个参数即可: 1.fileName excel文件名 2.HasMap<String,List<?&g

  • Java实现Excel导入导出数据库的方法示例

    本文实例讲述了Java实现Excel导入导出数据库的方法.分享给大家供大家参考,具体如下: 由于公司需求,想通过Excel导入数据添加到数据库中,而导入的Excel的字段是不固定的,使用得通过动态创建数据表,每个Excel对应一张数据表,怎么动态创建数据表,可以参考前面一篇<java使用JDBC动态创建数据表及SQL预处理的方法>. 下面主要讲讲怎么将Excel导入到数据库中,直接上代码:干货走起~~ ExcellToObjectUtil 类 主要功能是讲Excel中的数据导入到数据库中,有几

  • java实现Excel的导入、导出

    一.Excel的导入 导入可采用两种方式,一种是JXL,另一种是POI,但前者不能读取高版本的Excel(07以上),后者更具兼容性.由于对两种方式都进行了尝试,就都贴出来分享(若有错误,请给予指正) 方式一.JXL导入  所需jar包 JXL.jar publicstaticList<PutStorageInfo> readExcelByJXL(String filePath){ List<PutStorageInfo> infoList =newArrayList<Put

  • java实现合并单元格的同时并导出excel示例

    介绍 POI提供API给Java程序对Microsoft Office格式档案读和写的功能.POI可以操作的文档格式有excel,word,powerpoint等,POI进行跨行需要用到对象HSSFSheet对象,现在就当我们程序已经定义了一个HSSFSheet对象sheet. 跨第1行第1个到第2个单元格的操作为 sheet.addMergedRegion(new Region(0,(short)0,0,(short)1)); 跨第1行第1个到第2行第1个单元格的操作为 sheet.addMe

  • java实现导出Excel的功能

    导出excel是咱Java开发的必备技能啦,之前项目有这个功能,现在将其独立出来,分享一下. 所用技术就是SpringBoot,然后是MVC架构模式. 废话不多说,直接上代码了,源码点末尾链接就可以下载. (1)新建一个SpringBoot项目(可以官网https://start.spring.io/直接生成下载,然后导入eclipse),项目结构如下: (2)修改pom文件,添加依赖: <dependency> <groupId>org.springframework.boot&

  • Java数据导出功能之导出Excel文件实例

    在编程中经常需要使用到表格(报表)的处理主要以Excel表格为主.下面给出用java写入数据到excel表格方法: 1.添加jar文件 java导入导出Excel文件要引入jxl.jar包,最关键的是这套API是纯Java的,并不依赖Windows系统,即使运行在Linux下,它同样能够正确的处理Excel文件.下载地址:http://www.andykhan.com/jexcelapi/ 2.jxl对Excel表格的认识 可以参见:http://www.jb51.net/article/686

  • java导出Excel通用方法的实例详解

    java导出Excel通用方法的实例详解 Java导出Excel通用方法,只需要一个list 集合.通用方法改进之处踊跃提出 package oa.common.utils; import java.io.OutputStream; import java.util.List; import javax.servlet.http.HttpServletResponse; import org.apache.struts2.ServletActionContext; import java.lan

随机推荐