生成excel内存溢出问题的解决方式
常用的excel生成工具包括jxl、poi。但二者都存在一个问题:生成excel需要大量的消耗内存。如果一次性往excel中写入的数据足够的多将导致内存溢出。
1、数据写入excel为什么会大量的消耗内存?
这需要从excel特点以及jxl和poi的实现原理来分析。excel即表格,一个一个的单元格。我们生成excel就是往一个个的单元格里面写数据。如下代码(使用的jxl):
WritableWorkbook wwb = Workbook.createWorkbook(new File(fileName)); WritableSheet ws = wwb.createSheet(wjmc, 0); WritableFont wfont = new jxl.write.WritableFont( WritableFont.ARIAL, 10, WritableFont.NO_BOLD, false, UnderlineStyle.NO_UNDERLINE, jxl.format.Colour.BLACK); jxl.write.WritableCellFormat normalStyle = new jxl.write.WritableCellFormat(wfont); normalStyle.setLocked(true);// 保护单元格 /**写入文件表头 begin */ Label labelC = null; labelC = new Label(0, 0, "零件名称"); ws.addCell(labelC); labelC = new Label(1, 0, "精友零件编码"); ws.addCell(labelC); StringBuffer sycxString=null; if (rs != null) { int j = 1; while (rs.next()) { String id = rs.getString("id"); sycxList = getSycxList(id); sycxString = new StringBuffer(); if (sycxList != null) { for (Iterator it = sycxList.iterator(); it.hasNext();) { sycxString.append((String) it.next()).append("\n"); } } String commonPart=rs.getString("sec_id") == null?"否":"是"; labelC = new Label(0, j, rs.getString("ljmc"), normalStyle); ws.addCell(labelC); labelC = new Label(1, j, rs.getString("ljbm"), normalStyle); ws.addCell(labelC); j++; }
这是一段典型的excel生成代码。这样的逻辑在数据量小的时候没有问题。但一旦数据量大,如红色标注的那一行:每一个单元格都需要new一个对象。最重要的,这些对象被excel对象WritableSheet所引用,在excel整个生成完成前无法被回收。内存就这样被占据消耗了!如果多用户同时并发导出excel.....显然jvm内存溢出是必然的!
2、如何避免内存溢出?
上面分析的内存溢出的主要原因是当数据量大的时候,开辟的内存空间一直被占据着不释放。如果能缩短被占据的时间,内存就能及时被释放。从而避免内存溢出!要缩短被占据的时间,就要减少写入一个excel中的数据量。让单个的excel短时间内就能完全生成。即将大量的数据分批次写入到多个excel中!这样当一个excel生成完成之后,它所引用的单元格对象就能被回收释放。
poi3.8版本之后引入了一种全新的解决此类内存溢出的方法。如下代码:
Workbook wb = new SXSSFWorkbook(100); // keep 100 rows in memory, exceeding rows will be flushed to disk Sheet sh = wb.createSheet(); for(int rownum = 0; rownum < 100000; rownum++){ Row row = sh.createRow(rownum); for(int cellnum = 0; cellnum < 10; cellnum++){ Cell cell = row.createCell(cellnum); String address = new CellReference(cell).formatAsString(); cell.setCellValue(address); } } FileOutputStream out = new FileOutputStream("/temp/sxssf.xlsx"); wb.write(out); out.close();
在生成excel对象的时候可以指定其在内存中保留的数据量。超出指定数据量的数据后,会将之前的数据转到硬盘上。(注:此种方法是否有效个人尚未验证过)这样就避免了所有的单元格数据都保留在内存中,占据着不释放!
生成excel内存溢出问题的解决方式的更多相关文章
- Spark Shuffle 堆外内存溢出问题与解决(Shuffle通信原理)
Spark Shuffle 堆外内存溢出问题与解决(Shuffle通信原理) http://xiguada.org/spark-shuffle-direct-buffer-oom/ 问题描述 Spar ...
- Java虚拟机系列(三)---内存溢出情况及解决方法
因为Java虚拟机内存有堆内存.方法区.虚拟机栈.本地方法栈和程序计数器五部分组成,其中程序计数器是唯一一块不会发生内存溢出异常的内存区,所以只有四类内存区可能发生内存溢出异常,其中虚拟机栈和本地方法 ...
- Tomcat常见的内存溢出,以及解决方法
一.常见的三种内存溢出错误: 1.java.lang.OutOfMemoryError:java heap space ====JVM Heap(堆)溢出 JVM再启动的时候回自动设置JVM H ...
- C++中避免内存泄露常见的解决方式
常见内存泄露及解决方式-选自ood启发录 new/delete, array new/arrray delete匹配 case 1: 在类的构造函数与析构函数中没有匹配地调用 new/delete! ...
- java内存溢出的情况解决方法
内存溢出虽然很棘手,但也有相应的解决办法,可以按照从易到难,一步步的解决. 第一步,就是修改JVM启动参数,直接增加内存.这一点看上去似乎很简单,但很容易被忽略.JVM默认可以使用的内存为64M,To ...
- jmeter(二十二)内存溢出原因及解决方法
jmeter是一个java开发的开源性能测试工具,在性能测试中可支持模拟并发压测,但有时候当模拟并发请求较大或者脚本运行时间较长时,压力机会出现卡顿甚至报异常————内存溢出, 这里就介绍下如何解决内 ...
- <转>jmeter(二十二)内存溢出原因及解决方法
本博客转载自:http://www.cnblogs.com/imyalost/category/846346.html 个人感觉不错,对jmeter讲解非常详细,担心以后找不到了,所以转发出来,留着慢 ...
- [转]JVM内存溢出的几种方式比较
转载自:https://github.com/pzxwhc/MineKnowContainer/issues/25 包括: 1. 栈溢出(StackOverflowError) 2. 堆溢出(OutO ...
- jmeter 内存溢出原因及解决方法
jmeter是一个java开发的开源性能测试工具,在性能测试中可支持模拟并发压测,但有时候当模拟并发请求较大或者脚本运行时间较长时,压力机会出现卡顿甚至报异常————内存溢出, 这里就介绍下如何解决内 ...
随机推荐
- [Docker] Docker Client in Action
Pull the docker image: docker pull hello-world Show all the images: docker images Remove the image: ...
- TP框架多表联查
join方法import("@.ORG.Page"); $Form = M('gly'); $where=''; if ($_PO ...
- Mui实现退出登录
document.getElementById("logout").addEventListener("tap",function(){ var btn=[&q ...
- GSON 示例代码 实用版
去除所有格式的json字符串 {"data":[{"friend":[{"address":"广州","nam ...
- 有关Ajax实现的两种方法
首先我们来常见的Jquery式的Ajax写法,以及在java后台的取值 /** *AJAX */ function showLastTime(){ var facilityId = $('*[name ...
- Eclipse搭建struts2环境
搭建struts2环境 大的方面分为三步: 1. 加入jar包 2. 在web.xml中配置struts2 3. 添加struts2的配置文件struts.xml 下面是详细步骤: 1. 新建一个Dy ...
- C++ Primer 5th 第9章 顺序容器
练习9.1:对于下面的程序任务,vector.deque和list哪种容器最为适合?解释你的选择的理由.如果没有哪一种容器优于其他容器,也请解释理由.(a) 读取固定数量的单词,将它们按字典序插入到容 ...
- ubuntu 下 github 使用方法 以及异常修改
接触github很长时间了,github有windows 跟 mac 版本,恶心的是现在在linux 下没有可视化界面的版本.所以对于很多没有怎么接触过github的人带来很大困难.话不多说,彪重点: ...
- GDI相关函数
GetWindowRect计算窗口大小 MoveWindow 设置窗口大小 SetMapMode 该函数设置指定设备环境的映射方式 MM_LOMETRIC:每个逻辑单位转换为0.1毫米,X正方向向右, ...
- Codeforces739E Gosha is hunting
题意:现在有n个精灵,两种精灵球各m1和m2个,每个精灵单独使用第一种精灵球有pi的概率被捕获,单独使用第二种精灵球有ui的概率被捕获,同时使用有1-(1-pi)*(1-ui)的概率被捕获.一种精灵球 ...