生成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开发的开源性能测试工具,在性能测试中可支持模拟并发压测,但有时候当模拟并发请求较大或者脚本运行时间较长时,压力机会出现卡顿甚至报异常————内存溢出, 这里就介绍下如何解决内 ...
随机推荐
- 设计模式19---设计模式之状态模式(State)(行为型)
1.场景模拟 考虑一个在线投票的应用,分为四种情况 正常投票 正常投票以后还继续重复投票 用户恶意投票 黑名单用户 2.不用模式的解决方案 package demo17.state.example1; ...
- 要缩小通过两个触摸点的观点(iOS)
于AppDelegate.m档,创建一个视图控制器 #import "MAYAppDelegate.h" #import "MAYViewController.h&quo ...
- android开发步步为营之68:Facebook原生广告接入总结
开发应用的目的是干嘛?一方面当然是提供优质服务给用户,还有一方面最重要的还是须要有盈利.不然谁还有动力花钱花时间去开发app? 我们的应用主攻海外市场,所以主要还是接入国外的广告提供商.本文就今天刚完 ...
- [转] 强大的python字符串解析
1.python字符串通常有单引号('...').双引号("...").三引号("""...""")或('''...'' ...
- Visual Studio 2012 Ultimate 上安装 Python 开发插件 PTVS
1.我的环境 操作系统:32位 Win7 旗舰版 Service Pack 1 VS版本:Microsoft Visual Studio Ultimate 2012 版本 11.0.50727.1 R ...
- C# ashx生成的验证码
public void ProcessRequest(HttpContext context) { context.Response.ContentType = "image/jpeg&qu ...
- There is already an open DataReader associated with this Connection which must be closed first
使用MVC4 EF Linq获取foreach列表循环的时候遇到了如下的问题:报错提示 There is already an open DataReader associated with this ...
- Eclipse利用代理快速安装插件
在eclipse启动时增加以下参数: eclipse.exe -vmargs -DproxySet=true -DproxyHost=aProxyAddress -DproxyPort=aProxyP ...
- state模式理解
state模式应用场景 条件判断很多的情况 比如有很多if else语句:switch case语句等等. 如果以后业务越来越复杂,条件判断有100多个,每种条件的处理逻辑很复杂,不止一个业务逻辑会重 ...
- sql Server 常用存储过程的优化
优化存储过程有很多种方法,下面介绍最常用的7种. 1.使用SET NOCOUNT ON选项 我们使用SELECT语句时,除了返回对应的结果集外,还会返回相应的影响行数.使用SET NOCOUNT ON ...