今天在做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大量数据方法相关推荐

  1. Java利用Apace POI读取Excel中数据

    Java利用Apace POI读取Excel中数据,解析数据 @Testpublic void readExcel() throws IOException{FileSystemView fsv = ...

  2. java利用poi读取excel_java利用POI读取excel文件的方法

    摘要:利用java读取excel文件,读取文件并获取文件中每一个sheet中的值. 一.需要提前导入的包: import java.io.File; import java.io.FileInputS ...

  3. POI读取Excel文件数据

    1.封装类 import org.apache.commons.lang3.StringUtils; import org.apache.poi.ss.usermodel.*;import java. ...

  4. poi读取Excel内容数据

    public static void main(String[] args) { try{//获取文件输入流FileInputStream fileIn = new FileInputStream(& ...

  5. java通过POI快速读取excel大量数据的方式

    1.在pom.xml中引入poi相关依赖 <dependency><groupId>cn.afterturn</groupId><artifactId> ...

  6. java poi 模板填数据库,java使用POI读取excel模版并向固定表格里填写数据详解

    java使用POI读取excel模版并向固定表格里填写数据详解:public class ExportExcelDemo { private HSSFWorkbook workbook = null; ...

  7. Java使用Poi读取Excel数据(exor)

    读取Excel使用一个小工具exor exor是一个开源项目,封装了一些poi读取excel的操作,可以读取excel数据并格式化为二维结构 xlsx和xls格式都可以读取 exor的依赖:commo ...

  8. POI读取Excel模板并导出大量数据

    POI读取Excel模板并导出大量数据 我在使用XSSFWorkbook读取Excel模板并导出大量数据(百万级)时,发现很长时间没有响应,debugger模式发现在读取第三四十万条数据时,程序直接停 ...

  9. 使用POI读取Excel表格中数据

    使用POI读取Excel表格中数据 已经在 使用POI读取Excel表格中数据2优化.(https://blog.csdn.net/qq_36570464/article/details/107053 ...

最新文章

  1. 卷积神经网络(CNN)实现CIFAR100类别分类
  2. 2.合并区间(LeetCode第56题)
  3. python 条件表达式换行_Python基础语法 - LongKing-Xu的个人空间 - OSCHINA - 中文开源技术交流社区...
  4. Html.DropDownListFor练习(2)
  5. thymeleaf 中文_springboot 整合 thymeleaf(上手即用)
  6. 为什么EClipse不显示错误
  7. 在XML里的XSD和DTD以及standalone的使用
  8. 用计算机谈过火,央视电视文化中心过火网架的复建关键技术研究
  9. 后端根据查询条件生成excel文件返回给前端,vue进行下载
  10. springmvc jsp java_java-jsp springmvc-controller 传值到页面的方法
  11. iOS APP如何跳转小程序?友盟分享到微信的时候调不起微信是什么原因?
  12. appboot-7227
  13. Windows Azure Cloud Service (6) Reboot and Reimage
  14. kubeedge解决边端keadm join的时候卡住的问题
  15. 拈一朵不悔的缘识之花,为你静候流年
  16. linux查看进程号、端口号
  17. sja1000编程c语言,基于51单片机SJA1000 CAN通讯实现(C语言程序)
  18. short 在JAVA_short在java中是什么类型的
  19. Hadoop回收站trash
  20. 【Python】某商店T恤的价格为35元/件(2件9折,3件以上8折)裤子的价格为120元/条(2条以上9折).小明在该店买了3件T恤和2条裤子,请计算并显示小明应该付多少钱?

热门文章

  1. 荣耀平板7鸿蒙,消息称华为鸿蒙OS计划适配高通平台 荣耀平板X7 8英寸正式发布...
  2. E-study使用记录
  3. zufeoj 花生(The Peanuts)
  4. 与IPv4相比,IPv6具有哪些优势?
  5. JAVA 面试题 合辑(二)
  6. MATLAB调用.cpt文件的调色板
  7. 2019年陕西单招计算机机测试题,2019年陕西单招数学试题答案.pdf
  8. 如何让企业网站调用的视频没有广告
  9. 小米众筹新品---8H凉感慢回弹记忆绵枕 99元 上手开箱图
  10. Maya院线场景动画制作教程