常用的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内存溢出问题的解决方式的更多相关文章

  1. Spark Shuffle 堆外内存溢出问题与解决(Shuffle通信原理)

    Spark Shuffle 堆外内存溢出问题与解决(Shuffle通信原理) http://xiguada.org/spark-shuffle-direct-buffer-oom/ 问题描述 Spar ...

  2. Java虚拟机系列(三)---内存溢出情况及解决方法

    因为Java虚拟机内存有堆内存.方法区.虚拟机栈.本地方法栈和程序计数器五部分组成,其中程序计数器是唯一一块不会发生内存溢出异常的内存区,所以只有四类内存区可能发生内存溢出异常,其中虚拟机栈和本地方法 ...

  3. Tomcat常见的内存溢出,以及解决方法

    一.常见的三种内存溢出错误: 1.java.lang.OutOfMemoryError:java heap space    ====JVM Heap(堆)溢出 JVM再启动的时候回自动设置JVM H ...

  4. C++中避免内存泄露常见的解决方式

    常见内存泄露及解决方式-选自ood启发录 new/delete, array new/arrray delete匹配 case 1: 在类的构造函数与析构函数中没有匹配地调用 new/delete! ...

  5. java内存溢出的情况解决方法

    内存溢出虽然很棘手,但也有相应的解决办法,可以按照从易到难,一步步的解决. 第一步,就是修改JVM启动参数,直接增加内存.这一点看上去似乎很简单,但很容易被忽略.JVM默认可以使用的内存为64M,To ...

  6. jmeter(二十二)内存溢出原因及解决方法

    jmeter是一个java开发的开源性能测试工具,在性能测试中可支持模拟并发压测,但有时候当模拟并发请求较大或者脚本运行时间较长时,压力机会出现卡顿甚至报异常————内存溢出, 这里就介绍下如何解决内 ...

  7. <转>jmeter(二十二)内存溢出原因及解决方法

    本博客转载自:http://www.cnblogs.com/imyalost/category/846346.html 个人感觉不错,对jmeter讲解非常详细,担心以后找不到了,所以转发出来,留着慢 ...

  8. [转]JVM内存溢出的几种方式比较

    转载自:https://github.com/pzxwhc/MineKnowContainer/issues/25 包括: 1. 栈溢出(StackOverflowError) 2. 堆溢出(OutO ...

  9. jmeter 内存溢出原因及解决方法

    jmeter是一个java开发的开源性能测试工具,在性能测试中可支持模拟并发压测,但有时候当模拟并发请求较大或者脚本运行时间较长时,压力机会出现卡顿甚至报异常————内存溢出, 这里就介绍下如何解决内 ...

随机推荐

  1. js中内建对象

    JavaScript charAt() 函数 string.charAt(n) -- 返回指定位置(n)的字符 char是character的缩写,中文"符号,字符" 引用网址:h ...

  2. [转] 看懂UML类图和时序图

    PS: 组合关系:实心,一个类A属于另一个类,或多个类,但是类A不能单独存在去使用,A一般是一种抽象的东西 聚合关系:空心,一个类A可以单独存在使用 不论组合聚合,A的方法都会被直接调用. 看懂UML ...

  3. C#时间戳的获取与转换方法

    /// <summary> /// 获取当前时间戳 /// </summary> /// <param name="bflag"></pa ...

  4. spring07 JDBC

    1.创建对应的数据库 2.在MyEclipse中创建项目  引入需要的jar包 3.创建数据访问层 public interface StudentDao { //新增学生 int addStuden ...

  5. egrep和grep有什么区别

    grep默认不支持正则表达式,egrep默认支持正则表达式,egrep 等于 grep -E 命令.

  6. MySql中的时间类型datetime,timestamp,date,year比较

    MySQL日期类型.日期格式.存储空间.日期范围比较.日期类型        存储空间       日期格式                 日期范围------------ ---------   ...

  7. 认识html标签

    让我们通过一个网页的学习,来对html标签有一个初步理解. 平常大家说的上网就是浏览各种各式各样的网页,这些网页都是由html标签组成的. 下面就是一个简单的网页.效果图如下: 我们来分析一下,这个网 ...

  8. JS实现Tab切换

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  9. JavaWeb学习笔记之Servlet(二)

    1.  GenericServlet 抽象类: 1). 是一个 Serlvet. 是 Servlet 接口和 ServletConfig 接口的实现类. 但是一个抽象类. 其中的 service 方法 ...

  10. Win7下Solr4.10.1和TomCat8的安装

    1.系统为win7 64位系统,安装有wamp的环境,我的所有网站放在 d:\webserver下,域名指向该目录下的子目录: 2.安装TomCat8到 D:\Tomcat 8.0: 3.在 d:\w ...