重庆百宏互联网科技有限公司官方

Java 读取Excel大文件

发布日期:2021-12-24 00:09    点击次数:181

1、背景

业务方需求:随着我们商户不断增加,商户的数据需要一次性通过Excel导出到我们系统以初始化商户的数据。商户数据一般在几万左右使用一个Excel文件导入到我们业务系统,要求业务系统快速响应,数据尽快导入完成。

2、问题

需求方提出的Excel数据在几万,使用POI处理Excel比较消耗性能。

3、解决方案

使用excel-streaming-reader解决大Excel读取问题。

excel-streaming-readerGithub开源地址:https://github.com/monitorjbl/excel-streaming-reader

分页读取Excel分页处理

excel-streaming-reader只支持xlsx格式Excel

3.1、excel-streaming-reader性能-利用临时文件快速访问

以下是作者对excel-streaming-reader性能高的解释:

ThislibrarywilltakeaprovidedInputStreamandoutputittothefilesystem.Thestreamispipedsafelythroughaconfigurable-sizedbuffertopreventlargeusageofmemory.Oncethefileiscreated,itisthenstreamedintomemoryfromthefilesystem.ThereasonforneedingthestreambeingoutputtedinthismannerhastodowithhowZIPfileswork.BecausetheXLSXfileformatisbasicallyaZIPfile,it'snotpossibletofindalloftheentrieswithoutreadingtheentireInputStream.

Thisisaproblemthatcan'treallybegottenaroundforPOI,asitneedsacompletelistofZIPentries.ThedefaultimplementationofreadingfromanInputStreaminPOIistoreadtheentirestreamdirectlyintomemory.Thislibraryworksbyreadingoutthestreamintoatemporaryfile.Aspartoftheauto-closeaction,资讯中心thetemporaryfileisdeleted.

其实就是通过创建临时文件来提升性能,实现代码如下:

//创建临时文件

Filef=Files.createTempFile("tmp-",".xlsx").toFile;

//将原Excel文件复制到临时文件中

try(FileOutputStreamfos=newFileOutputStream(f)){

intread;

byte[]bytes=newbyte[bufferSize];

while((read=is.read(bytes))!=-1){

fos.write(bytes,0,read);

}

returnf;

}finally{

is.close;

}

3.2、excel-streaming-reader性能-利用小缓冲区缓存数据减少内存使用

3.3实施步骤

3.3.1、引入maven依赖

com.monitorjbl

xlsx-streamer

2.1.0

3.3.2、加载大Excel

InputStreamis=newFileInputStream(newFile("/path/to/workbook.xlsx"));

returnStreamingReader.builder

.rowCacheSize(100)//numberofrowstokeepinmemory(defaultsto10)

.bufferSize(4096)//buffersizetousewhenreadingInputStreamtofile(defaultsto1024)

.open(is);//InputStreamorFileforXLSXfile(required)

3.3.3、分页读取Excel

privateListnextPage(intpageSize,intsheetIndex){

Sheetsheet=this.wk.getSheetAt(sheetIndex);

intlimit=pageSize;

Listlist=newArrayList(limit);

for(Rowrow:sheet){

list.add(row);

limit--;

if(limit

break;

}

}

returnlist;

}

4、参考