POI 读取excel大量数据方法
今天在做excel文件上传时,发现数据量超过10万条后,系统会出现内存溢出。
跟踪代码发现程序卡在如下代码这里:
Workbook workbook=WorkbookFactory.create(new File(path));
通过poi的api发现此方法属于能对excel读写,但是内存消耗大,速度较慢。
在poi的官方文档中找到了读取大量数据的方法,但只能读数据,不能进行写操作。
代码整理如下
import java.io.InputStream;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.xssf.eventusermodel.XSSFReader;
import org.apache.poi.xssf.model.SharedStringsTable;
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
import org.junit.Test;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.XMLReaderFactory;/*** 数据量比较大(8万条以上)的excel文件解析,将excel文件解析为 行列坐标-值的形式存入map中,此方式速度快,内存耗损小 但只能读取excle文件* 提供处理单个sheet方法 processOneSheet(String filename) 以及处理多个sheet方法 processAllSheets(String filename)* 只需传入文件路径+文件名即可 调用处理方法结束后,只需 接收LargeExcelFileReadUtil.getRowContents()返回值即可获得解析后的数据**/
public class LargeExcelFileReadUtil {private LinkedHashMap<String, String>rowContents=new LinkedHashMap<String, String>(); private SheetHandler sheetHandler;public LinkedHashMap<String, String> getRowContents() {return rowContents;}public void setRowContents(LinkedHashMap<String, String> rowContents) {this.rowContents = rowContents;}public SheetHandler getSheetHandler() {return sheetHandler;}public void setSheetHandler(SheetHandler sheetHandler) {this.sheetHandler = sheetHandler;}//处理一个sheetpublic void processOneSheet(String filename) throws Exception {InputStream sheet2=null;OPCPackage pkg =null;try {pkg = OPCPackage.open(filename);XSSFReader r = new XSSFReader(pkg);SharedStringsTable sst = r.getSharedStringsTable();XMLReader parser = fetchSheetParser(sst);sheet2 = r.getSheet("rId1");InputSource sheetSource = new InputSource(sheet2);parser.parse(sheetSource);setRowContents(sheetHandler.getRowContents());}catch (Exception e) {e.printStackTrace();throw e;}finally{if(pkg!=null){pkg.close();}if(sheet2!=null){sheet2.close();}}}
//处理多个sheetpublic void processAllSheets(String filename) throws Exception {OPCPackage pkg =null;InputStream sheet=null;try{pkg=OPCPackage.open(filename);XSSFReader r = new XSSFReader( pkg );SharedStringsTable sst = r.getSharedStringsTable();XMLReader parser = fetchSheetParser(sst);Iterator<InputStream> sheets = r.getSheetsData();while(sheets.hasNext()) {System.out.println("Processing new sheet:\n");sheet = sheets.next();InputSource sheetSource = new InputSource(sheet);parser.parse(sheetSource);}}catch (Exception e) {e.printStackTrace();throw e;}finally{if(pkg!=null){pkg.close();}if(sheet!=null){sheet.close();}}}public XMLReader fetchSheetParser(SharedStringsTable sst) throws SAXException {XMLReader parser =XMLReaderFactory.createXMLReader("com.sun.org.apache.xerces.internal.parsers.SAXParser");setSheetHandler(new SheetHandler(sst));ContentHandler handler = (ContentHandler) sheetHandler;parser.setContentHandler(handler);return parser;}/** * See org.xml.sax.helpers.DefaultHandler javadocs *///测试@Testpublic void test ()throws Exception {Long time=System.currentTimeMillis();LargeExcelFileReadUtil example = new LargeExcelFileReadUtil();example.processOneSheet("C:/Users/Desktop/2018041310024112.xlsx");Long endtime=System.currentTimeMillis();LinkedHashMap<String, String> map=example.getRowContents();Iterator<Entry<String, String>> it= map.entrySet().iterator();int count=0;String prePos="";while (it.hasNext()){Map.Entry<String, String> entry=(Map.Entry<String, String>)it.next();String pos=entry.getKey();if(!pos.substring(1).equals(prePos)){prePos=pos.substring(1);count++;}System.out.println(pos+";"+entry.getValue());}System.out.println("解析数据"+count+"条;耗时"+(endtime-time)/1000+"秒");}
}/**
SheetHandler 类中处理从excle获取的数据,官方文档中 SheetHandler以内部类形式,为保证更新代码减少内部类class文件忘记打包,改为一般java类
*/
import java.util.LinkedHashMap;import org.apache.poi.xssf.model.SharedStringsTable;
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;public class SheetHandler extends DefaultHandler{private SharedStringsTable sst;private String lastContents;private boolean nextIsString;private String cellPosition;private LinkedHashMap<String, String>rowContents=new LinkedHashMap<String, String>(); public LinkedHashMap<String, String> getRowContents() {return rowContents;}public void setRowContents(LinkedHashMap<String, String> rowContents) {this.rowContents = rowContents;}public SheetHandler(SharedStringsTable sst) {this.sst = sst;}public void startElement(String uri, String localName, String name,Attributes attributes) throws SAXException {if(name.equals("c")) {// System.out.print(attributes.getValue("r") + " - ");cellPosition=attributes.getValue("r");String cellType = attributes.getValue("t");if(cellType != null && cellType.equals("s")) {nextIsString = true;} else {nextIsString = false;}}// 清楚缓存内容lastContents = "";}public void endElement(String uri, String localName, String name)throws SAXException {if(nextIsString) {int idx = Integer.parseInt(lastContents);lastContents = new XSSFRichTextString(sst.getEntryAt(idx)).toString();nextIsString = false;}if(name.equals("v")) {
// System.out.println("lastContents:"+cellPosition+";"+lastContents);//数据读取结束后,将单元格坐标,内容存入map中if(!(cellPosition.length()==2)||(cellPosition.length()==2&&!"1".equals(cellPosition.substring(1)))){//不保存第一行数据rowContents.put(cellPosition, lastContents);}}}public void characters(char[] ch, int start, int length)throws SAXException {lastContents += new String(ch, start, length);}
}
亲测可用,20多万条数据,4秒解析完,执行结果
poi jar包如下:
POI 读取excel大量数据方法相关推荐
- Java利用Apace POI读取Excel中数据
Java利用Apace POI读取Excel中数据,解析数据 @Testpublic void readExcel() throws IOException{FileSystemView fsv = ...
- java利用poi读取excel_java利用POI读取excel文件的方法
摘要:利用java读取excel文件,读取文件并获取文件中每一个sheet中的值. 一.需要提前导入的包: import java.io.File; import java.io.FileInputS ...
- POI读取Excel文件数据
1.封装类 import org.apache.commons.lang3.StringUtils; import org.apache.poi.ss.usermodel.*;import java. ...
- poi读取Excel内容数据
public static void main(String[] args) { try{//获取文件输入流FileInputStream fileIn = new FileInputStream(& ...
- java通过POI快速读取excel大量数据的方式
1.在pom.xml中引入poi相关依赖 <dependency><groupId>cn.afterturn</groupId><artifactId> ...
- java poi 模板填数据库,java使用POI读取excel模版并向固定表格里填写数据详解
java使用POI读取excel模版并向固定表格里填写数据详解:public class ExportExcelDemo { private HSSFWorkbook workbook = null; ...
- Java使用Poi读取Excel数据(exor)
读取Excel使用一个小工具exor exor是一个开源项目,封装了一些poi读取excel的操作,可以读取excel数据并格式化为二维结构 xlsx和xls格式都可以读取 exor的依赖:commo ...
- POI读取Excel模板并导出大量数据
POI读取Excel模板并导出大量数据 我在使用XSSFWorkbook读取Excel模板并导出大量数据(百万级)时,发现很长时间没有响应,debugger模式发现在读取第三四十万条数据时,程序直接停 ...
- 使用POI读取Excel表格中数据
使用POI读取Excel表格中数据 已经在 使用POI读取Excel表格中数据2优化.(https://blog.csdn.net/qq_36570464/article/details/107053 ...
最新文章
- 卷积神经网络(CNN)实现CIFAR100类别分类
- 2.合并区间(LeetCode第56题)
- python 条件表达式换行_Python基础语法 - LongKing-Xu的个人空间 - OSCHINA - 中文开源技术交流社区...
- Html.DropDownListFor练习(2)
- thymeleaf 中文_springboot 整合 thymeleaf(上手即用)
- 为什么EClipse不显示错误
- 在XML里的XSD和DTD以及standalone的使用
- 用计算机谈过火,央视电视文化中心过火网架的复建关键技术研究
- 后端根据查询条件生成excel文件返回给前端,vue进行下载
- springmvc jsp java_java-jsp springmvc-controller 传值到页面的方法
- iOS APP如何跳转小程序?友盟分享到微信的时候调不起微信是什么原因?
- appboot-7227
- Windows Azure Cloud Service (6) Reboot and Reimage
- kubeedge解决边端keadm join的时候卡住的问题
- 拈一朵不悔的缘识之花,为你静候流年
- linux查看进程号、端口号
- sja1000编程c语言,基于51单片机SJA1000 CAN通讯实现(C语言程序)
- short 在JAVA_short在java中是什么类型的
- Hadoop回收站trash
- 【Python】某商店T恤的价格为35元/件(2件9折,3件以上8折)裤子的价格为120元/条(2条以上9折).小明在该店买了3件T恤和2条裤子,请计算并显示小明应该付多少钱?