注意:此参考解决方案只是针对xlsx格式的excel文件!

背景

前一段时间遇到一种情况,服务器经常宕机,而且没有规律性,查看GC日志发生了out of memory,是堆溢出导致的,分析了一下堆的dump文件,发现在发生OOM时创建了大量的String对象。最后对照时间点,发现宕机的时候业务人员在上传一个excel文件,但是这个excel文件才28MB大小,感觉应该不会引起内存溢出。后来在本地启动了服务,然后尝试上传这个excel文件,同时使用Java VisualVM监控GC情况,发现在上传的时候,创建了大量的String对象,后来老年代没有可分配空间导致了OOM。最终分析结果是,excel文件中存在几十万的空行数据,表面上看,这些空行数据跟不存在数据的行是一样的,但是POI会把这种空行数据读入到内存中,感觉这也是一个坑。

在网上搜了很长时间,发现国内网站上的解决方案真是没法看,基本上答案都差不多,没有什么有见解性的解决方法,后来在stackoverflow上找到了解决方法。算是给自己做一下备注,也想帮助一些还在坑里的人,就分享一下,只是自己的见解,有不得当的地方也请见谅。

常规读取方法

通常在读取excel文件时(.xlsx),是使用如下代码进行加载的:

FileInputStream fi = new FileInputStream("e:/2.xlsx");
XSSFWorkbook wk = new XSSFWorkbook(fi);

然后再获取对应的Sheet、Row和Cell,然后获取excel中的内容,但是这种方式POI会把文件的所有内容都加载到内存中,读取大的excel文件时很容易占用大量内存。

尝试解决方法

使用Excel Streaming Reader,这个第三方工具会把一部分的行(可以设置)缓存到内存中,在迭代时不断加载行到内存中,而不是一次性的加载所有记录到内存,这样就可以不断的读取excel内容并且不影响内存的使用。

但是这个工具也有一定的限制:只能用于读取excel的内容,写入操作不可用;可以使用getSheetAt()方法获取到对应的Sheet,因为当前只是加载了有限的row在内存中,因此不能随机访问row,即不能使用getRow(int rowNum)方法;由于行数据已经加载到了内存,因此可以随机的访问Cell数据,即可以使用getCell(int cellnum)方法。使用这个工具,建议使用迭代器来进行迭代。具体内容可以参见:https://github.com/monitorjbl/excel-streaming-reader。

在pom.xml文件中引入需要的jar包:

        <dependency>
<groupId>com.monitorjbl</groupId>
<artifactId>xlsx-streamer</artifactId>
<version>1.2.0</version>
</dependency>

使用代码如下:

    @Test
public void testLoad() throws Exception{
FileInputStream in = new FileInputStream("e:/2.xlsx");
Workbook wk = StreamingReader.builder()
.rowCacheSize(100) //缓存到内存中的行数,默认是10
.bufferSize(4096) //读取资源时,缓存到内存的字节大小,默认是1024
.open(in); //打开资源,必须,可以是InputStream或者是File,注意:只能打开XLSX格式的文件
Sheet sheet = wk.getSheetAt(0);
//遍历所有的行
for (Row row : sheet) {
System.out.println("开始遍历第" + row.getRowNum() + "行数据:");
//遍历所有的列
for (Cell cell : row) {
System.out.print(cell.getStringCellValue() + " ");
}
System.out.println(" ");
}
}

参考资料:https://stackoverflow.com/questions/11891851/how-to-load-a-large-xlsx-file-with-apache-poi

Java中使用POI读取大的Excel文件或者输入流时发生out of memory异常参考解决方案的更多相关文章

  1. Java中使用poi导入、导出Excel

    一.介绍 当前B/S模式已成为应用开发的主流,而在企业办公系统中,常常有客户这样子要求:你要把我们的报表直接用Excel打开(电信系统.银行系统).或者是:我们已经习惯用Excel打印.这样在我们实际 ...

  2. Java 使用Apache POI读取和写入Excel表格

    1,引入所用的包 <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxm ...

  3. java使用org.apache.poi读取与保存EXCEL文件

    一.读EXCEL文件 package com.ruijie.wis.cloud.utils; import java.io.FileInputStream; import java.io.FileNo ...

  4. Java使用POI读取和写入Excel指南

    Java使用POI读取和写入Excel指南 做项目时经常有通过程序读取Excel数据,或是创建新的Excel并写入数据的需求: 网上很多经验教程里使用的POI版本都比较老了,一些API在新版里已经废弃 ...

  5. java使用poi读取doc和docx文件(maven自动导入依赖包)

    java使用poi读取doc和docx文件(maven自动导入依赖包) 于是在网上搜寻了一阵之后才发现原来doc文档和excel一样不能用普通的io流的方法来读取,而是也需要用poi,于是进行了一番尝 ...

  6. lucent检索技术之创建索引:使用POI读取txt/word/excel/ppt/pdf内容

    在使用lucent检索文档时,必须先为各文档创建索引.索引的创建即读出文档信息(如文档名称.上传时间.文档内容等),然后再经过分词建索引写入到索引文件里.这里主要是总结下读取各类文档内容这一步. 一. ...

  7. 如何用 php 读取一个很大的 excel 文件。

    这个程序是用php 读取一个很大的excel文件, 先将 excel 文件保存成csv 文件, 然后利用 迭代器 逐行读取 excel 单元格的值, 拿到值以后 做相应处理,并打印结果. <?p ...

  8. 【Java/JDBC】借助ResultSetMetaData,从数据库表中抽取字段信息存成Excel文件

    本例工程下载:https://files.cnblogs.com/files/xiandedanteng/FindNotnullColumns20191102-3.rar 工作中曾有个为42张表建立测 ...

  9. 【转】Python xlrd、xlwt、xlutils读取、修改Excel文件

    Python xlrd.xlwt.xlutils读取.修改Excel文件 一.xlrd读取excel 这里介绍一个不错的包xlrs,可以工作在任何平台.这也就意味着你可以在Linux下读取Excel文 ...

随机推荐

  1. net core 程序docker打包镜像并发布到官方store

    学习一个技术的第一步,总是要先打印或显示一个hello world的.当然,学习docker也不例外.上一篇文章已经简单的介绍了环境的安装和配置.接下来就要打印我们的hello world了. 首先我 ...

  2. Codeforces Round #419 (Div. 2)

    1.题目A:Karen and Morning 题意: 给出hh:mm格式的时间,问至少经过多少分钟后,该时刻为回文字符串? 思路: 简单模拟,从当前时刻开始,如果hh的回文rh等于mm则停止累计.否 ...

  3. AngularJS的文字溢出处理

    需求大致如图所示,由于本人也是新接触AngularJS,研究好久,制作了一个demo,代码如下: <!DOCTYPE html><html><head><me ...

  4. uwp版的音乐播放器练手

    UWP项目之音乐播放器 这个项目本来是我女朋友的一个小作业,她做不出来,结果只能是我来代劳.经过几天的时间虽然赶出来了,但是自己不是很满意,还有很多不满意的地方,因此决定在最近的一段时间内,重新完成. ...

  5. loadrunner 手工参数拼接与l oadrunner的url编码

    Acction() { //演示需要的一些变量,提前声明 char *name = "yezi_zh"; "; char *work = "engin" ...

  6. 【Android Developers Training】 84. 将定期更新的影响最小化

    注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...

  7. Latex加速: TexStudio的安装和使用

    TexStudio可以加速Latex的编辑和写作,这里简单介绍一下TexStudio的安装,配置和使用.但是有一个重要的前提,TexStudio会使Latex源代码和pdf文件并排显示,比较占用桌面的 ...

  8. 改变图像,运用match方法判断

    <!DOCTYPE html><html><head> <meta charset="utf-8"> <title>菜鸟 ...

  9. js实现两个输入框中的数字相乘并自动将结果显示在第三个输入框

    <script type="text/javascript"> function cal(ida,idb,idc) { var numa=Number(document ...

  10. 实现一个简单的Log框架

    实际上算不上框架,只是自己对日志框架的一点理解. 核心接口:Logger,供调用者完成不同等级的日志输出 package com.lichmama.log.service; public interf ...