说明:我的电脑 2.0CPU 2G内存 能够十秒钟导出 20W 条数据 ,12.8M的excel内容压缩后2.68M

我们知道在POI导出Excel时,数据量大了,很容易导致内存溢出。由于Excel 一个sheet允许的最大行数是65536这时我们想到分sheet进行导出;但是这种情况也不能解决内存溢出的问题。毕竟数据还是一次性在内存中进行保存的。这时我们想是不是可以导出多个excel呢?下面我就尝试着按照导出多个excel

首先:我们要确定数据量有多大,然后确定一个excel导出多少条数据,这样就可以确定导出的Excel的数量,于是我们就可以循环的导出excel并保存在任意的临时目录中。去这样如果内存不够的话虚拟机就会去进行回收已经保存的excel在内存中的空间。

假设我们我们已经成功的生成了多个excel,这时我们怎么把这N个excel文档传到客户端呢?其实一个一个的传也未尝不可,但是考虑那样对用户来说体验不够好,再次多个文件在网络上传输也比较慢。我们可以考虑对生成的几个文件进行压缩,然后传到客户端。

总结一下第一、分批次生成excel第二、压缩后到客户端

下面我把我的一个小实例贴上供大家参考

第一、Person.java 普通javabean

package bean;

/**

*

* @author http://javaflex.iteye.com/

*

*/

public class Person {

private Integer id;

private String name;

private String address;

private String tel;

private Double money=0.0;

public Double getMoney() {

return money;

}

public void setMoney(Double money) {

this.money = money;

}

public Person(Integer id, String name, String address, String tel,Double money) {

super();

this.id = id;

this.name = name;

this.address = address;

this.tel = tel;

this.money=money;

}

public Integer getId() {

return id;

}

public void setId(Integer id) {

this.id = id;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public String getAddress() {

return address;

}

public void setAddress(String address) {

this.address = address;

}

public String getTel() {

return tel;

}

public void setTel(String tel) {

this.tel = tel;

}

}

第二、PersonService模拟业务逻辑循环生成100023个Person对象

package service;

import java.util.ArrayList;

import java.util.List;

import bean.Person;

/**

*

* @author http://javaflex.iteye.com/

*

*/

public class PersonService {

public static List getPerson(){

List list =new ArrayList();

for(int i=0;i<100320;i++){

list.add(new Person(i,"zhangsan"+i,"北京"+i,"13214587632",123123.12+i));

}

return list;

}

}

第三、业务处理Servlet

package servlet;

import java.io.File;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.OutputStream;

import java.text.SimpleDateFormat;

import java.util.ArrayList;

import java.util.Date;

import java.util.List;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;

import org.apache.poi.hssf.util.CellRangeAddress;

import org.apache.poi.ss.usermodel.Cell;

import org.apache.poi.ss.usermodel.CellStyle;

import org.apache.poi.ss.usermodel.Row;

import org.apache.poi.ss.usermodel.Sheet;

import org.apache.poi.ss.usermodel.Workbook;

import bean.Person;

import service.PersonService;

/**

*

* @author http://javaflex.iteye.com/

*

*/

public class PersonServlet extends HttpServlet {

private String fileName;

public PersonServlet() {

super();

}

public void destroy() {

super.destroy(); // Just puts "destroy" string in log

// Put your code here

}

public void doGet(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

// 文件名获取

Date date = new Date();

SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");

String f = "Person-" + format.format(date);

this.fileName = f;

setResponseHeader(response);

OutputStream out = null;

try {

out = response.getOutputStream();

List list = PersonService.getPerson();

toExcel(list,request,10000,f,out);

} catch (IOException e1) {

e1.printStackTrace();

} finally {

try {

out.flush();

out.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

/** 设置响应头 */

public void setResponseHeader(HttpServletResponse response) {

try {

response.setContentType("application/octet-stream;charset=UTF-8");

response.setHeader("Content-Disposition", "attachment;filename="

+ java.net.URLEncoder.encode(this.fileName, "UTF-8")

+ ".zip");

response.addHeader("Pargam", "no-cache");

response.addHeader("Cache-Control", "no-cache");

} catch (Exception ex) {

ex.printStackTrace();

}

}

public void doPost(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {

doGet(request, response);

}

public void init() throws ServletException {

// Put your code here

}

public void toExcel(List list, HttpServletRequest request,

int length, String f, OutputStream out) throws IOException {

List fileNames = new ArrayList();// 用于存放生成的文件名称s

File zip = new File(request.getRealPath("/files") + "/" + f + ".zip");// 压缩文件

// 生成excel

for (int j = 0, n = list.size() / length + 1; j < n; j++) {

Workbook book = new HSSFWorkbook();

Sheet sheet = book.createSheet("person");

double d = 0;// 用来统计

String file = request.getRealPath("/files") + "/" + f + "-" + j

+ ".xls";

fileNames.add(file);

FileOutputStream o = null;

try {

o = new FileOutputStream(file);

// sheet.addMergedRegion(new

// CellRangeAddress(list.size()+1,0,list.size()+5,6));

Row row = sheet.createRow(0);

row.createCell(0).setCellValue("ID");

row.createCell(1).setCellValue("NAME");

row.createCell(2).setCellValue("ADDRESS");

row.createCell(3).setCellValue("TEL");

row.createCell(4).setCellValue("Money");

int m = 1;

for (int i = 1, min = (list.size() - j * length + 1) > (length + 1) ? (length + 1)

: (list.size() - j * length + 1); i < min; i++) {

m++;

Person user = list.get(length * (j) + i - 1);

Double dd = user.getMoney();

if (dd == null) {

dd = 0.0;

}

d += dd;

row = sheet.createRow(i);

row.createCell(0).setCellValue(user.getId());

row.createCell(1).setCellValue(user.getName());

row.createCell(2).setCellValue(user.getAddress());

row.createCell(3).setCellValue(user.getTel());

row.createCell(4).setCellValue(dd);

}

CellStyle cellStyle2 = book.createCellStyle();

cellStyle2.setAlignment(CellStyle.ALIGN_CENTER);

row = sheet.createRow(m);

Cell cell0 = row.createCell(0);

cell0.setCellValue("Total");

cell0.setCellStyle(cellStyle2);

Cell cell4 = row.createCell(4);

cell4.setCellValue(d);

cell4.setCellStyle(cellStyle2);

sheet.addMergedRegion(new CellRangeAddress(m, m, 0, 3));

} catch (Exception e) {

e.printStackTrace();

}

try {

book.write(o);

} catch (Exception ex) {

ex.printStackTrace();

} finally {

o.flush();

o.close();

}

}

File srcfile[] = new File[fileNames.size()];

for (int i = 0, n = fileNames.size(); i < n; i++) {

srcfile[i] = new File(fileNames.get(i));

}

util.FileZip.ZipFiles(srcfile, zip);

FileInputStream inStream = new FileInputStream(zip);

byte[] buf = new byte[4096];

int readLength;

while (((readLength = inStream.read(buf)) != -1)) {

out.write(buf, 0, readLength);

}

inStream.close();

}

}

最后还有个工具类package util;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.IOException;

import java.util.zip.ZipEntry;

import java.util.zip.ZipOutputStream;

/**

*

* @author http://javaflex.iteye.com/

*

*/

public class FileZip {

/**

*

* @param srcfile 文件名数组

* @param zipfile 压缩后文件

*/

public static void ZipFiles(java.io.File[] srcfile, java.io.File zipfile) {

byte[] buf = new byte[1024];

try {

ZipOutputStream out = new ZipOutputStream(new FileOutputStream(

zipfile));

for (int i = 0; i < srcfile.length; i++) {

FileInputStream in = new FileInputStream(srcfile[i]);

out.putNextEntry(new ZipEntry(srcfile[i].getName()));

int len;

while ((len = in.read(buf)) > 0) {

out.write(buf, 0, len);

}

out.closeEntry();

in.close();

}

out.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

OK全部内容完成

12.8M的excel内容压缩后2.68M,给力吧

以后记得代码加注释

亲,记得给个评论哦

大小: 4.4 KB

大小: 2.5 KB

POI.rar (5.7 MB)

下载次数: 1836

17

1

分享到:

2011-11-17 14:42

浏览 47577

评论

19 楼

liangzzong

2018-03-07

厉害了,又学会一招。

18 楼

羽翼的心动

2017-02-21

自己用过一款中间件产品叫做pageoffice,批量导出word,excel代码非常简单,而且很稳定呢,poi代码有点多,比较繁琐,推荐楼主用pageoffice。

17 楼

贝塔ZQ

2017-01-03

poi导出大量数据,这样比较麻烦,代码也比较复杂,还得区分xls格式和xlsx格式的文件,可以用pageoffice插件,很好使的。

16 楼

张进飞

2015-07-27

存放数据list,如果数据量比较大会溢出

15 楼

aa00aa00

2014-11-16

楼主好,刚才测试一下,测试导出1000320,100w条数据,压缩后的包能有27.8m,速速还行,谢谢

14 楼

zzj_rjkf

2014-10-13

你好 我参考你的代码!但是导出4万条数据时!报内存溢出!QQ:1424557018!有时间帮我解答一下 谢了

感谢博主分享!

12 楼

ae6623

2014-06-24

573281868mengyong 写道

双击下载的zip文件,为什么报错"C:\Documents and Settings\wot_mengyong\桌面\Person-20140416131433.zip: 不可预料的压缩文件末端".解压出来就没问题.这是为什么呢?

可能你的excel文件在制作的过程中出现问题了,比如后缀名,比如poi的Style样式使用过多等原因。

双击下载的zip文件,为什么报错"C:\Documents and Settings\wot_mengyong\桌面\Person-20140416131433.zip: 不可预料的压缩文件末端".解压出来就没问题.这是为什么呢?

双击下载的zip文件,为什么报错"C:\Documents and Settings\wot_mengyong\桌面\Person-20140416131433.zip: 不可预料的压缩文件末端".解压出来就没问题.这是为什么呢?

9 楼

ae6623

2013-11-25

ae6623 写道

楼主,超级给力!!!楼下的你们就知道来挑刺,自己去做啊?人家楼主抛砖引玉出来不是让你们挑刺的,想挑刺,贴解决代码啊。一群眼高手低的人。poi大数据,谁都知道要分页,还用你们强调?楼主是一个简单的Demo,真正用到产品里肯定是调优的。能把这个放出来,你们百度到就已经很给力了,要有感激的心。楼主好样的。下面解决一下并发的问题。大数据量5W条*40多列的情况下20个并发在was6.5 2GJvm下直接服务卡死了。poi3.8据说可以限制内存释放,但是不支持2003xls格式,所以我也在想办法继续搞。10000条导出一次,压缩包导出最好了。

解决方法就是使用poi-3.10最新版的,里面可以自动释放内存,不过只支持Excel2007以上格式,生成文件后缀改为xlsx。非常爽,无内存溢出,还需要自己手动清空一下表格即可,清空方法为:

int rowInMemory = 100;// 100测试最佳

// 刷新到硬盘

SXSSFWorkbook wb = new SXSSFWorkbook(rowInMemory); // keep 100 rows in memory,

//临时文件进行压缩,建议不要true,否则会影响导出时间

wb.setCompressTempFiles(false);

// sheet名字

SXSSFSheet sheet = (SXSSFSheet) wb.createSheet(sheetName);

最后的最后你可以手动释放内存,强制刷新sheet到硬盘。

// 刷新到硬盘

sheet.flushRows();

logger.debug("-----------------------------flush ok-----------------------------------");

bodys.clear();

bodys = null;

logger.debug("内存制作数据已经结束!");

// 拿到输出流

fos = new FileOutputStream(file);

// 缓冲

outr = new BufferedOutputStream(fos);

// 生成excel

wb.write(outr);

outr.flush();

outr.close();

8 楼

H4X0R

2013-10-21

学习一下

7 楼

ae6623

2013-09-17

楼主,超级给力!!!楼下的你们就知道来挑刺,自己去做啊?人家楼主抛砖引玉出来不是让你们挑刺的,想挑刺,贴解决代码啊。一群眼高手低的人。poi大数据,谁都知道要分页,还用你们强调?楼主是一个简单的Demo,真正用到产品里肯定是调优的。能把这个放出来,你们百度到就已经很给力了,要有感激的心。楼主好样的。下面解决一下并发的问题。大数据量5W条*40多列的情况下20个并发在was6.5 2GJvm下直接服务卡死了。poi3.8据说可以限制内存释放,但是不支持2003xls格式,所以我也在想办法继续搞。10000条导出一次,压缩包导出最好了。

6 楼

c.hle2008

2013-03-14

这个应该是属于假分页式的导出数据。

5 楼

红旗无风不飘

2012-06-12

不知道你这个效率怎么样,如果创建多个Sheet是不是会好一些

4 楼

yn5411

2011-11-18

如果导出XLS,大数话都必须这样分文件做。

3 楼

javaflex

2011-11-18

Reset 写道

List list = PersonService.getPerson();

toExcel(list,request,10000,f,out);

代码不够优雅,应分页读出写入excel,而不是一次性从数据库里读出20W数据

大数据量的导入导出数据一般使用文本格式的中介存储,根本没必要放到excel。

这个地方确实应该分页导出

2 楼

Reset

2011-11-18

List list = PersonService.getPerson();

toExcel(list,request,10000,f,out);

代码不够优雅,应分页读出写入excel,而不是一次性从数据库里读出20W数据

大数据量的导入导出数据一般使用文本格式的中介存储,根本没必要放到excel。

1 楼

ZZX19880809

2011-11-18

不错,能简单应用了

easypoi 批量导出_POI导出大量数据的简单解决方案(附源码)相关推荐

  1. 手把手教你做一个数据图表生成器(附源码)...

    我的需求:手动配置X轴.Y轴.图表标题等参数自动通过Pyecharts模块生成可视化的html数据图表,并将浏览器图表展示到UI界面上. [阅读全文] 制作出图表后的效果展示如下: 另外,生成后的图表 ...

  2. flink sql 知其所以然(二)| 自定义 redis 数据维表(附源码)

    感谢您的关注  +  点赞 + 再看,对博主的肯定,会督促博主持续的输出更多的优质实战内容!!! 1.序篇-本文结构 背景篇-为啥需要 redis 维表 目标篇-做 redis 维表的预期效果是什么 ...

  3. 前端复杂表格一键导出看这篇就够了(附源码)

    大厂技术  高级前端  Node进阶 点击上方 程序员成长指北,关注公众号 回复1,加入高级Node交流群 前端导出 excel 的需求很多,但市面上好用的库并不多,讲明白复杂使用场景的文章更少. 本 ...

  4. 【爬虫实战项目】Python爬虫批量下载音乐飙升榜并保存本地(附源码)

    前言 今天给大家介绍的是Python爬虫批量下载音乐飙升榜并保存本地,在这里给需要的小伙伴们代码,并且给出一点小心得. 首先是爬取之前应该尽可能伪装成浏览器而不被识别出来是爬虫,基本的是加请求头,但是 ...

  5. Vue使用ECharts完成2020年全国各地区GDP总量大数据可视化面板(附源码)

    就在上周全国各地区GDP总量上了热搜,一时兴起就想写个大数据面板展示 既然决定要写,那么就要考虑到图表和图标的使用,这里我是用了我最熟悉的两大框架ECharts和element-ui 一.我的构思步骤 ...

  6. 前端vue显示柱状图_详解Vue2+Echarts实现多种图表数据可视化Dashboard(附源码)_旧址_前端开发者...

    数据可视化 将数据通过图表的形式展现出来将大大的提升可读性和阅读效率 本例包含柱状图.折线图.散点图.热力图.复杂柱状图.预览面板等 技术栈 vue2.x vuex 存储公共变量,如色值等 eleme ...

  7. ssm通用数据展示系统 毕业设计-附源码200934

    SSM通用数据展示系统的设计与实现 摘 要 随着社会信息化的日益加强,传统的数据处理系统存在专用性太强.安全性不高.数据共享性差等缺陷,不利于企业应用.为了充分利用企业信息资产所带来的优势,企业迫切需 ...

  8. 【Java项目】讲讲我用Java爬虫获取LOL英雄数据与图片(附源码)

  9. leaflet 结合 d3.js 实现 geojson 数据地形剖面分析(附源码下载)

    前言 leaflet 入门开发系列环境知识点了解: leaflet api文档介绍,详细介绍 leaflet 每个类的函数以及属性等等 leaflet 在线例子 leaflet 插件,leaflet ...

最新文章

  1. python日期格式化
  2. 前沿·探索·想象力,今年的云栖大会有啥不一样?
  3. 寻找字符串中第一个仅仅出现一次打字符
  4. Pyhton随机生成测试数据模块faker
  5. java 重命名_Java如何重命名文件?
  6. react实现聊天界面_React-Redux 100行代码简易版探究原理
  7. html中多个div分开排列,CSS+DIV设计实例:多个DIV排列时居中
  8. 【C语言】标准内容介绍(C99)
  9. 前端工程化——Livereload和HMR、本地开发服务器
  10. ArcGIS应用(十六)Arcgis 点对连线制作航空线路图
  11. StartUml 用例图
  12. Unity动画系统详解1:在Unity中如何制作动画?
  13. 360视频:CMP和ACP投影
  14. LSB文本水印的嵌入与提取
  15. 结巴(jieba)分词的使用-Java实现
  16. freetype的安装与使用
  17. 【STM32】SPI协议通信详解
  18. 金蝶K3生产任务单批次号和工单号同步需求实现
  19. Android Studio:增加蒙板/浮层特效
  20. 如何真正的隐藏文件夹

热门文章

  1. Android 使用Json表情包
  2. HP840笔记本电脑如何截屏
  3. JAVAFX 使用mybatis-plus整合sqlite 操作数据库,保存成功,但数据库没有数据
  4. 一加6怎么刷android p6,安卓手机好评棒出炉: 魅族P6P抢占第三, 第一是谁?
  5. RabbitMQ-使用消息队列实现分布式事务
  6. 上传视频到阿里云服务器
  7. 战鬼如何杀小黄红石头
  8. c语言变量类型double,C语言double数据类型介绍、示例和应用经验
  9. csdn写博客,在MarkDown下复制IDE编辑器中的代码,导致csdn笔记排版变乱
  10. uniapp实现六个格子输入框