java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Java导出超大Excel文件

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

作者:冰子杍

导出excel是咱Java开发的必备技能,下面这篇文章主要给大家介绍了关于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文件内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文