溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Java如何通過(guò)導(dǎo)出超大Excel文件解決內(nèi)存溢出問(wèn)題

發(fā)布時(shí)間:2021-09-26 13:55:13 來(lái)源:億速云 閱讀:709 作者:小新 欄目:開(kāi)發(fā)技術(shù)

這篇文章將為大家詳細(xì)講解有關(guān)Java如何通過(guò)導(dǎo)出超大Excel文件解決內(nèi)存溢出問(wèn)題,小編覺(jué)得挺實(shí)用的,因此分享給大家做個(gè)參考,希望大家閱讀完這篇文章后可以有所收獲。

1.采用Poi中的SXSSFWorkbook

在實(shí)現(xiàn)excel導(dǎo)出時(shí),在數(shù)據(jù)量過(guò)大的情況下,總是容易發(fā)生內(nèi)存溢出的情況。可以使用POI提供的 SXSSFWorkbook 類來(lái)避免內(nèi)存溢出。

Java如何通過(guò)導(dǎo)出超大Excel文件解決內(nèi)存溢出問(wèn)題

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.測(cè)試過(guò)程

先使用普通的寫(xiě)法測(cè)試(XSSFWorkbook),編寫(xiě)writeNormalExcelTest測(cè)試方法,寫(xiě)入的行數(shù)太多時(shí),會(huì)報(bào)內(nèi)存溢出(在設(shè)置-server -Xmx64m -Xms64m -Xmn32m的情況下)。

接著編寫(xiě)SXSSFWorkbook操作excel的測(cè)試,測(cè)試方法writeHugeExcelTest(同樣在設(shè)置-server -Xmx64m -Xms64m -Xmn32m的情況下),結(jié)果證明無(wú)內(nèi)存溢出,能完好的導(dǎo)出1000000行測(cè)試數(shù)據(jù),整個(gè)Java類代碼如下:

4.單元測(cè)試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; //寫(xiě)入的excel數(shù)據(jù)行數(shù)
	private int totalCellNumber = 40; //excel每行共40列
	
	//普通的寫(xiě)入excel的方法,會(huì)消耗內(nèi)存,寫(xiě)入的行數(shù)太大時(shí),會(huì)報(bào)內(nèi)存溢出
	@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開(kāi)始.
	       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()); //寫(xiě)入一個(gè)隨機(jī)數(shù)
	           }
	            
	           //打印測(cè)試,
	           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();
			}
	    	
	    }
		
	}
	
	//結(jié)合臨時(shí)文件壓縮等寫(xiě)入excel,默認(rèn)超過(guò)100行就寫(xiě)到臨時(shí)文件,不會(huì)報(bào)內(nèi)存溢出
	@Test
	public void writeHugeExcelTest(){

        SXSSFWorkbook wb = null;
        FileOutputStream out = null;
        
        try {
        	
        	long startTime = System.currentTimeMillis();
        	
            wb = new SXSSFWorkbook();//默認(rèn)100行,超100行將寫(xiě)入臨時(shí)文件
            wb.setCompressTempFiles(false); //是否壓縮臨時(shí)文件,否則寫(xiě)入速度更快,但更占磁盤(pán),但程序最后是會(huì)將臨時(shí)文件刪掉的
            Sheet sheet = wb.createSheet("Sheet 1");
            
            //定義Row和Cell變量, Rows從0開(kāi)始.
	        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()); //寫(xiě)入一個(gè)隨機(jī)數(shù)
	            }
	        	
	        	
	        	//打印測(cè)試,
	            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();// 刪除臨時(shí)文件,很重要,否則磁盤(pán)可能會(huì)被寫(xiě)滿
            }
            
            try {
				if(out != null) out.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
	    	
		    try {
		    	if(wb != null) wb.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		    
        }
		
	}

}

關(guān)于“Java如何通過(guò)導(dǎo)出超大Excel文件解決內(nèi)存溢出問(wèn)題”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,使各位可以學(xué)到更多知識(shí),如果覺(jué)得文章不錯(cuò),請(qǐng)把它分享出去讓更多的人看到。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI