• 用过POI的人都知道,在POI以前的版本中并不支持大数据量的处理,如果数据...性能并不是太好),好在POI3.8版本新出来了一个SXSSFWorkbook对象,它就是用来解决大数据量以及超大数据量的导入导出操作的,但是SXSSFWorkbo
       用过POI的人都知道,在POI以前的版本中并不支持大数据量的处理,如果数据量过多还会常报OOM错误,这时候调整JVM的配置参数也不是一个好对策(注:jdk在32位系统中支持的内存不能超过2个G,而在64位中没有限制,但是在64位的系统中,性能并不是太好),好在POI3.8版本新出来了一个SXSSFWorkbook对象,它就是用来解决大数据量以及超大数据量的导入导出操作的,但是SXSSFWorkbook只支持.xlsx格式,不支持.xls格式的Excel文件。

    这里普及一下,POI中使用HSSF对象时,excel 2003最多只允许存储65536条数据,一般用来处理较少的数据量,这时对于百万级别数据,Excel肯定容纳不了,而且在计算机性能稍低的机器上测试,就很容易导致堆溢出。而当我升级到XSSF对象时,它可以直接支持excel2007以上版本,因为它采用ooxml格式。这时excel可以支持1048576条数据,单个sheet表就支持近104万条数据了,虽然这时导出100万数据能满足要求,但使用XSSF测试后发现偶尔还是会发生堆溢出,所以也不适合百万数据的导出

     现在我们知道excel2007及以上版本可以轻松实现存储百万级别的数据,但是系统中的大量数据是如何能够快速准确的导入到excel中这好像是个难题,对于一般的web系统,我们为了解决成本,基本都是使用的入门级web服务器tomcat,既然我们不推荐调整JVM的大小,那我们就要针对我们的代码来解决我们要解决的问题。在POI3.8之后新增加了一个类,SXSSFWorkbook,采用当数据加工时不是类似前面版本的对象,它可以控制excel数据占用的内存,他通过控制在内存中的行数来实现资源管理,即当创建对象超过了设定的行数,它会自动刷新内存,将数据写入文件,这样导致打印时,占用的CPU,和内存很少。但有人会说了,我用过这个类啊,他好像并不能完全解决,当数据量超过一定量后还是会内存溢出的,而且时间还很长。对你只是用了这个类,但是你并没有针对你的需求进行相应的设计,仅仅是用了,所以接下来我要说的问题就是,如何通过SXSSFWorkbook以及相应的写入设计来实现百万级别的数据快速写入。

     我先举个例子,以前我们数据库中存在大量的数据,我们要查询,怎么办?我们在没有经过设计的时候是这样来处理的,先写一个集合,然后执行jdbc,将返回的结果赋值给list,然后再返回到页面上,但是当数据量大的时候,就会出现数据无法返回,内存溢出的情况,于是我们在有限的时间和空间下,通过分页将数据一页一页的显示出来,这样可以避免了大数据量数据对内存的占用,也提高了用户的体验,在我们要导出的百万数据也是一个道理,内存突发性占用,我们可以限制导出数据所占用的内存,这里我先建立一个list容器,list中开辟10000行的存储空间,每次存储10000行,用完了将内容清空,然后重复利用,这样就可以有效控制内存,所以我们的设计思路就基本形成了,所以分页数据导出共有以下3个步骤:

    1、求数据库中待导出数据的行数

    2、根据行数求数据提取次数

    3、按次数将数据写入文件

    通过以上步骤在效率和用户体验性上都有了很高的提高,接下来上代码

    public void exportBigDataExcel(ValueDataDto valueDataDto, String path)
    			throws IOException {
    	// 最重要的就是使用SXSSFWorkbook,表示流的方式进行操作
    	// 在内存中保持100行,超过100行将被刷新到磁盘
    	SXSSFWorkbook wb = new SXSSFWorkbook(100);
    	Sheet sh = wb.createSheet(); // 建立新的sheet对象
    	Row row = sh.createRow(0);   // 创建第一行对象
    	// -----------定义表头-----------
    	Cell cel0 = row.createCell(0);
    	cel0.setCellValue("1");
    	Cell cel2 = row.createCell(1);
    	cel2.setCellValue("2");
    	Cell cel3 = row.createCell(2);
    	cel3.setCellValue("3");
    	Cell cel4 = row.createCell(3);
    	// ---------------------------
    	List<valuedatabean> list = new ArrayList<valuedatabean>();
    	// 数据库中存储的数据行
    	int page_size = 10000;
    	// 求数据库中待导出数据的行数
    	int list_count = this.daoUtils.queryListCount(this.valueDataDao
    			.queryExportSQL(valueDataDto).get("count_sql"));
    	// 根据行数求数据提取次数
    	int export_times = list_count % page_size > 0 ? list_count / page_size
    			+ 1 : list_count / page_size;
    	// 按次数将数据写入文件
    	for (int j = 0; j < export_times; j++) {
    		list = this.valueDataDao.queryPageList(this.valueDataDao
    				.queryExportSQL(valueDataDto).get("list_sql"), j + 1,
    				page_size);
    		int len = list.size() < page_size ? list.size() : page_size;
    	
    <span style="white-space:pre">	</span>	for (int i = 0; i < len; i++) {
    			Row row_value = sh.createRow(j * page_size + i + 1);
    			Cell cel0_value = row_value.createCell(0);
    			cel0_value.setCellValue(list.get(i).getaa());
    			Cell cel2_value = row_value.createCell(1);
    			cel2_value.setCellValue(list.get(i).getaa());
    			Cell cel3_value = row_value.createCell(2);
    			cel3_value.setCellValue(list.get(i).getaa_person());
    		}
    		list.clear(); // 每次存储len行,用完了将内容清空,以便内存可重复利用
    	}
    	FileOutputStream fileOut = new FileOutputStream(path);
    	wb.write(fileOut);
    	fileOut.close();
    	wb.dispose();
    }

    到目前已经可以实现百万数据的导出了,但是当我们的业务数据超过200万,300万了呢?如何解决?

    这时,直接打印数据到一个工作簿的一个工作表是实现不了的,必须拆分到多个工作表,或者多个工作簿中才能实现。因为一个sheet最多行数为1048576

    下面就以这种思路提供另外一种解决方案,直接上代码(后面会附上测试数据库,及案例需要的jar包)

    public static void main(String[] args) throws Exception {
    	Test3SXXFS tm = new Test3SXXFS();
    	tm.jdbcex(true);
    }
    public void jdbcex(boolean isClose) throws InstantiationException, IllegalAccessException, 
    			ClassNotFoundException, SQLException, IOException, InterruptedException {
    		
    	String xlsFile = "f:/poiSXXFSBigData.xlsx";		//输出文件
    	//内存中只创建100个对象,写临时文件,当超过100条,就将内存中不用的对象释放。
    	Workbook wb = new SXSSFWorkbook(100);			//关键语句
    	Sheet sheet = null;		//工作表对象
    	Row nRow = null;		//行对象
    	Cell nCell = null;		//列对象
    
    	//使用jdbc链接数据库
    	Class.forName("com.mysql.jdbc.Driver").newInstance();  
    	String url = "jdbc:mysql://localhost:3306/bigdata?characterEncoding=UTF-8";
    	String user = "root";
    	String password = "123456";
    	//获取数据库连接
    	Connection conn = DriverManager.getConnection(url, user,password);   
    	Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE);   
    	String sql = "select * from hpa_normal_tissue limit 1000000";   //100万测试数据
    	ResultSet rs = stmt.executeQuery(sql);  
    	
    	ResultSetMetaData rsmd = rs.getMetaData();
    	long  startTime = System.currentTimeMillis();	//开始时间
    	System.out.println("strat execute time: " + startTime);
    		
    	int rowNo = 0;		//总行号
    	int pageRowNo = 0;	//页行号
    		
    	while(rs.next()) {
    		//打印300000条后切换到下个工作表,可根据需要自行拓展,2百万,3百万...数据一样操作,只要不超过1048576就可以
    		if(rowNo%300000==0){
    			System.out.println("Current Sheet:" + rowNo/300000);
    			sheet = wb.createSheet("我的第"+(rowNo/300000)+"个工作簿");//建立新的sheet对象
    			sheet = wb.getSheetAt(rowNo/300000);		//动态指定当前的工作表
    			pageRowNo = 0;		//每当新建了工作表就将当前工作表的行号重置为0
    		}	
    		rowNo++;
    		nRow = sheet.createRow(pageRowNo++);	//新建行对象
    
    		// 打印每行,每行有6列数据   rsmd.getColumnCount()==6 --- 列属性的个数
    		for(int j=0;j<rsmd.getColumnCount();j++){
    			nCell = nRow.createCell(j);
    			nCell.setCellValue(rs.getString(j+1));
    		}
    			
    		if(rowNo%10000==0){
    			System.out.println("row no: " + rowNo);
    		}
    //		Thread.sleep(1);	//休息一下,防止对CPU占用,其实影响不大
    	}
    		
    	long finishedTime = System.currentTimeMillis();	//处理完成时间
    	System.out.println("finished execute  time: " + (finishedTime - startTime)/1000 + "m");
    		
    	FileOutputStream fOut = new FileOutputStream(xlsFile);
    	wb.write(fOut);
    	fOut.flush();		//刷新缓冲区
    	fOut.close();
    		
    	long stopTime = System.currentTimeMillis();		//写文件时间
    	System.out.println("write xlsx file time: " + (stopTime - startTime)/1000 + "m");
    		
    	if(isClose){
    		this.close(rs, stmt, conn);
    	}
    }
    	
    //执行关闭流的操作
    private void close(ResultSet rs, Statement stmt, Connection conn ) throws SQLException{
    	rs.close();   
    	stmt.close();   
    	conn.close(); 
    }

    数据库截图:




    案例执行结果截图:

                 


    完美!!!!


    数据库脚本及案例相关jar包:

    http://pan.baidu.com/s/1pKXQp55


    展开全文
  • maven 依赖 (版本必须一致,否则使用SXSSFworkbook 时...org.apache.poi&lt;/groupId&gt; &lt;artifactId&gt;poi&lt;/artifactId&gt; &lt;version&gt;3.9&lt;/version&gt;

    maven 依赖 (版本必须一致

    ,否则使用SXSSFworkbook 时程序会报错)

    <dependency>
          <groupId>org.apache.poi</groupId>
          <artifactId>poi</artifactId>
          <version>3.9</version>
        </dependency>
        <dependency>
          <groupId>org.apache.poi</groupId>
          <artifactId>poi-ooxml</artifactId>
          <version>3.9</version>
        </dependency>

    HSSFworkbook,XSSFworkbook,SXSSFworkbook 三者 区别

    HSSFworkbook:操作Excel2003版本,扩展名为xls

    XSSFworkbook:操作Excel2007版本,扩展名为xlsx

    SXSSFworkbook :用于大数据量导出,当数据量超过 65536后 程序 会报错:Invalid row number (65536) outside allowable range (0..65535)


    例子1:简单导出Excel

    @Test
        public void test1() throws IOException {
            // 读取文件
            POIFSFileSystem fs = new POIFSFileSystem(Thread.currentThread().getContextClassLoader().getResourceAsStream("test.xls"));
            // 创建一个工作簿
            HSSFWorkbook workbook = new HSSFWorkbook(fs);
            // 获取第一个sheet
            HSSFSheet sheet = workbook.getSheetAt(0);
            System.out.println(sheet.getSheetName());
            // 获取第一行
            HSSFRow row = sheet.getRow(0);
            // 获取第一行第一列
            HSSFCell cell = row.getCell(0);
            System.out.println(cell.getStringCellValue());
    
            // 创建一行
            HSSFRow row1 = sheet.createRow(1);
            // 创建单元格
            HSSFCell cell1 = row1.createCell(0);
            // 单元格赋值
            cell1.setCellValue("我是程序创建的内容");
            System.out.println(cell1.getStringCellValue());
    
            // 创建输出流
            FileOutputStream os = new FileOutputStream(new File("D:\\8888.xls"));
            // 输出文件
            workbook.write(os);
        }

    例子2:导出查询数据

    @Test
        public void test2() {
            // 模拟导出数据
            Object[] obj = new Object[]{"哈哈", "呵呵", "哼哼"};
            List<Object[]> list = new ArrayList<Object[]>();
            // HSSFWorkbook 只支持2003版本及以下版本Excel 且容量最大为65536
            for (int i = 0; i < 65536; i++) {
                list.add(obj);
            }
    
            export("test.xls", list, 2);
        }
    
        /**
         * poi 导出
         * @param fileName
         * @param objs
         * @param rowIndex
         */
        private void export(String fileName, List<Object[]> objs, int rowIndex) {
            POIFSFileSystem fs = null;
            FileOutputStream os = null;
            try {
                fs = new POIFSFileSystem(Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName));
            } catch (IOException e) {
                e.printStackTrace();
            }
            // 创建一个工作簿
            try {
                HSSFWorkbook workbook = new HSSFWorkbook(fs);
                HSSFCellStyle style = setCellStyle(workbook);
                // 获取一个sheet页
                HSSFSheet sheet = workbook.getSheetAt(0);
    
                for (int i = rowIndex - 1; i < objs.size(); i++) {
                    // 创建行
                    HSSFRow row = sheet.createRow(i);
    
                    // 创建列
                    for (int j = 0; j < objs.get(i).length; j++) {
                        HSSFCell cell = row.createCell(j);
                        // 设置单元格样式
                        cell.setCellStyle(style);
                        cell.setCellValue(objs.get(i)[j].toString());
                    }
                }
                // 创建输出流
                 os = new FileOutputStream(new File("D:\\8888.xls"));
                // 输出文件
                workbook.write(os);
            } catch (IOException e) {
                e.printStackTrace();
            }finally {
                if (os != null) {
                    try {
                        os.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    
    
        /**
         * 设置样式
         * @param workbook
         */
        private HSSFCellStyle setCellStyle(HSSFWorkbook workbook) {
            HSSFCellStyle style = workbook.createCellStyle();
            HSSFFont font = workbook.createFont();
            // 字号
            font.setFontHeightInPoints((short) 12);
            style.setFont(font);
            // 左右居中 上下居中
            style.setAlignment(HSSFCellStyle.ALIGN_CENTER);
            style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);
            return style;
        }

    例子3:大数据量导出

    /**
         * 大数据量导出
         * @throws IOException
         */
        @Test
        public void text2() throws IOException {
    
            XSSFWorkbook xssfWorkbook = new   XSSFWorkbook(Thread.currentThread().getContextClassLoader().getResourceAsStream("bigdata.xlsx"));
            SXSSFWorkbook wb = new SXSSFWorkbook(xssfWorkbook, 100);
    
            Sheet sh = wb.getSheetAt(0);
            for(int rownum = 1; rownum < 75537; 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);
                }
    
            }
    
    //        // Rows with rownum < 900 are flushed and not accessible
    //        for(int rownum = 0; rownum < 900; rownum++){
    //            Assert.assertNull(sh.getRow(rownum));
    //        }
    //
    //        // ther last 100 rows are still in memory
    //        for(int rownum = 900; rownum < 1000; rownum++){
    //            Assert.assertNotNull(sh.getRow(rownum));
    //        }
    
            FileOutputStream out = new FileOutputStream("D:\\sxssf.xlsx");
            wb.write(out);
            out.close();
    
            // dispose of temporary files backing this workbook on disk
            wb.dispose();
        }

    展开全文
  • Java实现导出excel表格功能,大部分都会使用apache poi, apache poi API 地址

    Java实现导出excel表格功能,大部分都会使用apache poi,apache poi API 地址
    POI之前的版本不支持大数据量处理,如果数据过多则经常报OOM错误,有时候调整JVM大小效果也不是太好。3.8版本的POI新出来了SXSSFWorkbook,可以支持大数据量的操作,只是SXSSFWorkbook只支持.xlsx格式,不支持.xls格式。
    3.8版本的POI对excel的导出操作,一般只使用HSSFWorkbook以及SXSSFWorkbook,HSSFWorkbook用来处理较少的数据量,SXSSFWorkbook用来处理大数据量以及超大数据量的导出。
    代码:
    git地址 有3.9jar包

    package qs.test;
    
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    
    import org.apache.poi.ss.usermodel.Cell;
    import org.apache.poi.ss.usermodel.Row;
    import org.apache.poi.ss.usermodel.Sheet;
    import org.apache.poi.ss.util.CellReference;
    import org.apache.poi.xssf.streaming.SXSSFWorkbook;
    
    /**
     * ClassName: SXSSFTest
     * @Description: TODO
     * @author qiaoshuai
     */
    public class SXSSFTest {
    
        public static void main(String[] args) throws IOException {
            // 创建基于stream的工作薄对象的
            SXSSFWorkbook wb = new SXSSFWorkbook(100); // keep 100 rows in memory,
                                                        // exceeding rows will be
                                                        // flushed to disk
            // SXSSFWorkbook wb = new SXSSFWorkbook();
            // wb.setCompressTempFiles(true); // temp files will be gzipped
            Sheet sh = wb.createSheet();
            // 使用createRow将信息写在内存中。
            for (int rownum = 0; rownum < 1000; 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);
                }
    
            }
    
            // Rows with rownum < 900 are flushed and not accessible
            // 当使用getRow方法访问的时候,将内存中的信息刷新到硬盘中去。
            for (int rownum = 0; rownum < 900; rownum++) {
                System.out.println(sh.getRow(rownum));
            }
    
            // ther last 100 rows are still in memory
            for (int rownum = 900; rownum < 1000; rownum++) {
                System.out.println(sh.getRow(rownum));
            }
            // 写入文件中
            FileOutputStream out = new FileOutputStream("G://sxssf.xlsx");
            wb.write(out);
            // 关闭文件流对象
            out.close();
            System.out.println("基于流写入执行完毕!");
        }
    
    }
    

    在此基础上再优化的方案是导出的Excel表格生成多个工作表即生成多个sheet。
    代码:

    import java.io.IOException;
    import java.io.UnsupportedEncodingException;
    import java.net.URLEncoder;
    import java.util.ArrayList;
    import java.util.Date;
    import java.util.LinkedHashMap;
    import java.util.List;
    
    import org.springframework.http.HttpHeaders;
    import org.springframework.http.HttpStatus;
    import org.springframework.http.MediaType;
    import org.springframework.http.ResponseEntity;
    
    import com.common.DateFormatUtil;
    
    public class ExlUtil2 {
    
        /**
         * @param excelHeader
         *            表头信息
         * @param list
         *            要导出到excel的数据源,List类型
         * @param sheetName
         *            表名
         * @return
         */
        public static ResponseEntity<byte[]> getDataStream(ExcelHeader excelHeader,
                List list, String sheetName) {
            LinkedHashMap<String, List> map = new LinkedHashMap<String, List>();
            List<String[]> headNames = new ArrayList<String[]>();
            List<String[]> fieldNames = new ArrayList<String[]>();
            String[] sheetNames = new String[100];
            //处理Excel生成多个工作表 
            //定义为每个工作表数据为50000条
            if (list.size() > 50000) {
                int k = (list.size() + 50000) / 50000;
                for (int i = 1; i <= k; i++) {
                    if (i < k) {
                        map.put(sheetName + i,
                                list.subList((i - 1) * 50000, i * 50000));
                    } else {
                        map.put(sheetName + i,
                                list.subList((i - 1) * 50000, list.size()));
                    }
    
                    headNames.add(excelHeader.getHeadNames().get(0));
                    fieldNames.add(excelHeader.getFieldNames().get(0));
                    sheetNames[i - 1] = sheetName;
                }
    
            } else {
                map.put(sheetName, list);
                headNames.add(excelHeader.getHeadNames().get(0));
                fieldNames.add(excelHeader.getFieldNames().get(0));
                sheetNames[0] = sheetName;
            }
    
            byte[] buffer = null;
    
            try {
                buffer = ExcelUtil2.output(headNames, fieldNames, sheetNames, map);
    
            } catch (IllegalArgumentException | IllegalAccessException
                    | IOException e) {
                e.printStackTrace();
            }
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
    
            /*
             * try { sheetName=URLEncoder.encode(sheetName,"UTF8"); } catch
             * (UnsupportedEncodingException e) { e.printStackTrace(); }
             */
            try {
                sheetName = new String(sheetName.getBytes("gbk"), "iso-8859-1");
            } catch (UnsupportedEncodingException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            String fileGenerateTime = DateFormatUtil.toStr(new Date());
            headers.setContentDispositionFormData("attachment", sheetName
                    + fileGenerateTime + ".xlsx");
            return new ResponseEntity<byte[]>(buffer, headers, HttpStatus.CREATED);
        };
    
    }
    

    代码

    展开全文
  • POI 对大数据量的导出是一个难点,这里博主总结了两种处理方式: 方式一,使用高版本的POI,具有内存自动释放的特点。 方式二,将数据导出到多个Excel中,并进行压缩处理,上传到服务器中。 方式...

    POI 对大数据量的导出是一个难点,这里博主总结了两种处理方式:


    方式一,使用高版本的POI,具有内存自动释放的特点。


    方式二,将数据导出到多个Excel中,并进行压缩处理,上传到服务器中。




    方式一:


    POI之前的版本不支持大数据量处理,如果数据过多则经常报OOM错误,有时候调整JVM大小效果也不是太好。3.8版本的POI新出来了SXSSFWorkbook,可以支持大数据量的操作,只是SXSSFWorkbook只支持.xlsx格式,不支持.xls格式。

        3.8版本的POI对excel的导出操作,一般只使用HSSFWorkbook以及SXSSFWorkbook,HSSFWorkbook用来处理较少的数据量,SXSSFWorkbook用来处理大数据量以及超大数据量的导出。
        HSSFWorkbook的使用方法和之前的版本的使用方法一致,这里就不在陈述使用方法了
        SXSSFWorkbook的使用例子如下:
    import junit.framework.Assert;
    import org.apache.poi.ss.usermodel.Cell; 
    import org.apache.poi.ss.usermodel.Row; 
    import org.apache.poi.ss.usermodel.Sheet; 
    import org.apache.poi.ss.usermodel.Workbook; 
    import org.apache.poi.ss.util.CellReference; 
    import org.apache.poi.xssf.streaming.SXSSFWorkbook;  
    public static void main(String[] args) throws Throwable { 
     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();
    以前还用xml来处理,现在3.8以上就好办了。
    原文地址是:http://blog.sina.com.cn/s/blog_68555ee501015xk2.html
    apache官网相关内容地址:http://poi.apache.org/spreadsheet/how-to.html#sxssf







    方式二:


    说明:我的电脑 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

     

    Javabean代码  收藏代码
    1. package bean;  
    2. /**  
    3.  *   
    4.  * @author http://javaflex.iteye.com/  
    5.  *  
    6.  */  
    7. public class Person {  
    8.   
    9.     private Integer id;  
    10.     private String name;  
    11.     private String address;  
    12.     private String tel;  
    13.     private Double money=0.0;  
    14.     public Double getMoney() {  
    15.         return money;  
    16.     }  
    17.     public void setMoney(Double money) {  
    18.         this.money = money;  
    19.     }  
    20.     public Person(Integer id, String name, String address, String tel,Double money) {  
    21.         super();  
    22.         this.id = id;  
    23.         this.name = name;  
    24.         this.address = address;  
    25.         this.tel = tel;  
    26.         this.money=money;  
    27.     }  
    28.     public Integer getId() {  
    29.         return id;  
    30.     }  
    31.     public void setId(Integer id) {  
    32.         this.id = id;  
    33.     }  
    34.     public String getName() {  
    35.         return name;  
    36.     }  
    37.     public void setName(String name) {  
    38.         this.name = name;  
    39.     }  
    40.     public String getAddress() {  
    41.         return address;  
    42.     }  
    43.     public void setAddress(String address) {  
    44.         this.address = address;  
    45.     }  
    46.     public String getTel() {  
    47.         return tel;  
    48.     }  
    49.     public void setTel(String tel) {  
    50.         this.tel = tel;  
    51.     }  
    52. }  

     

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

     

    模拟业务逻辑代码  收藏代码
    1. package service;  
    2.   
    3. import java.util.ArrayList;  
    4. import java.util.List;  
    5.   
    6. import bean.Person;  
    7. /**  
    8.  *   
    9.  * @author http://javaflex.iteye.com/  
    10.  *  
    11.  */  
    12. public class PersonService {  
    13.     public static List getPerson(){  
    14.         List<Person> list =new ArrayList<Person>();  
    15.         for(int i=0;i<100320;i++){  
    16.             list.add(new Person(i,"zhangsan"+i,"北京"+i,"13214587632",123123.12+i));    
    17.         }  
    18.         return list;  
    19.     }  
    20.   
    21. }  

     

     第三、业务处理Servlet

     

    操作servlet代码  收藏代码
    1. package servlet;  
    2.   
    3. import java.io.File;  
    4. import java.io.FileInputStream;  
    5. import java.io.FileOutputStream;  
    6. import java.io.IOException;  
    7. import java.io.OutputStream;  
    8. import java.text.SimpleDateFormat;  
    9. import java.util.ArrayList;  
    10. import java.util.Date;  
    11. import java.util.List;  
    12.   
    13. import javax.servlet.ServletException;  
    14. import javax.servlet.http.HttpServlet;  
    15. import javax.servlet.http.HttpServletRequest;  
    16. import javax.servlet.http.HttpServletResponse;  
    17.   
    18. import org.apache.poi.hssf.usermodel.HSSFWorkbook;  
    19. import org.apache.poi.hssf.util.CellRangeAddress;  
    20. import org.apache.poi.ss.usermodel.Cell;  
    21. import org.apache.poi.ss.usermodel.CellStyle;  
    22. import org.apache.poi.ss.usermodel.Row;  
    23. import org.apache.poi.ss.usermodel.Sheet;  
    24. import org.apache.poi.ss.usermodel.Workbook;  
    25.   
    26. import bean.Person;  
    27.   
    28. import service.PersonService;  
    29.   
    30. /**  
    31.  *   
    32.  * @author http://javaflex.iteye.com/  
    33.  *  
    34.  */  
    35. public class PersonServlet extends HttpServlet {  
    36.     private String fileName;  
    37.   
    38.     public PersonServlet() {  
    39.         super();  
    40.     }  
    41.   
    42.     public void destroy() {  
    43.         super.destroy(); // Just puts "destroy" string in log  
    44.         // Put your code here  
    45.     }  
    46.   
    47.     public void doGet(HttpServletRequest request, HttpServletResponse response)  
    48.             throws ServletException, IOException {  
    49.         // 文件名获取  
    50.         Date date = new Date();  
    51.         SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");  
    52.         String f = "Person-" + format.format(date);  
    53.         this.fileName = f;  
    54.         setResponseHeader(response);  
    55.         OutputStream out = null;  
    56.         try {  
    57.             out = response.getOutputStream();  
    58.             List<Person> list = PersonService.getPerson();  
    59.             toExcel(list,request,10000,f,out);  
    60.         } catch (IOException e1) {  
    61.             e1.printStackTrace();  
    62.         } finally {  
    63.             try {  
    64.                 out.flush();  
    65.                 out.close();  
    66.             } catch (IOException e) {  
    67.                 e.printStackTrace();  
    68.             }  
    69.         }  
    70.     }  
    71.   
    72.     /** 设置响应头 */  
    73.     public void setResponseHeader(HttpServletResponse response) {  
    74.         try {  
    75.             response.setContentType("application/octet-stream;charset=UTF-8");  
    76.             response.setHeader("Content-Disposition""attachment;filename="  
    77.                     + java.net.URLEncoder.encode(this.fileName, "UTF-8")  
    78.                     + ".zip");  
    79.             response.addHeader("Pargam""no-cache");  
    80.             response.addHeader("Cache-Control""no-cache");  
    81.         } catch (Exception ex) {  
    82.             ex.printStackTrace();  
    83.         }  
    84.     }  
    85.     public void doPost(HttpServletRequest request, HttpServletResponse response)  
    86.             throws ServletException, IOException {  
    87.   
    88.         doGet(request, response);  
    89.     }  
    90.     public void init() throws ServletException {  
    91.         // Put your code here  
    92.     }  
    93.   
    94.     public void toExcel(List<Person> list, HttpServletRequest request,  
    95.             int length, String f, OutputStream out) throws IOException {  
    96.         List<String> fileNames = new ArrayList();// 用于存放生成的文件名称s  
    97.         File zip = new File(request.getRealPath("/files") + "/" + f + ".zip");// 压缩文件  
    98.         // 生成excel  
    99.         for (int j = 0, n = list.size() / length + 1; j < n; j++) {  
    100.             Workbook book = new HSSFWorkbook();  
    101.             Sheet sheet = book.createSheet("person");  
    102.   
    103.             double d = 0;// 用来统计  
    104.             String file = request.getRealPath("/files") + "/" + f + "-" + j  
    105.                     + ".xls";  
    106.   
    107.             fileNames.add(file);  
    108.             FileOutputStream o = null;  
    109.             try {  
    110.                 o = new FileOutputStream(file);  
    111.   
    112.                 // sheet.addMergedRegion(new  
    113.                 // CellRangeAddress(list.size()+1,0,list.size()+5,6));  
    114.                 Row row = sheet.createRow(0);  
    115.                 row.createCell(0).setCellValue("ID");  
    116.                 row.createCell(1).setCellValue("NAME");  
    117.                 row.createCell(2).setCellValue("ADDRESS");  
    118.                 row.createCell(3).setCellValue("TEL");  
    119.                 row.createCell(4).setCellValue("Money");  
    120.   
    121.                 int m = 1;  
    122.   
    123.                 for (int i = 1, min = (list.size() - j * length + 1) > (length + 1) ? (length + 1)  
    124.                         : (list.size() - j * length + 1); i < min; i++) {  
    125.                     m++;  
    126.                     Person user = list.get(length * (j) + i - 1);  
    127.                     Double dd = user.getMoney();  
    128.                     if (dd == null) {  
    129.                         dd = 0.0;  
    130.                     }  
    131.                     d += dd;  
    132.                     row = sheet.createRow(i);  
    133.                     row.createCell(0).setCellValue(user.getId());  
    134.                     row.createCell(1).setCellValue(user.getName());  
    135.                     row.createCell(2).setCellValue(user.getAddress());  
    136.                     row.createCell(3).setCellValue(user.getTel());  
    137.                     row.createCell(4).setCellValue(dd);  
    138.   
    139.                 }  
    140.                 CellStyle cellStyle2 = book.createCellStyle();  
    141.                 cellStyle2.setAlignment(CellStyle.ALIGN_CENTER);  
    142.                 row = sheet.createRow(m);  
    143.                 Cell cell0 = row.createCell(0);  
    144.                 cell0.setCellValue("Total");  
    145.                 cell0.setCellStyle(cellStyle2);  
    146.                 Cell cell4 = row.createCell(4);  
    147.                 cell4.setCellValue(d);  
    148.                 cell4.setCellStyle(cellStyle2);  
    149.                 sheet.addMergedRegion(new CellRangeAddress(m, m, 03));  
    150.             } catch (Exception e) {  
    151.                 e.printStackTrace();  
    152.             }  
    153.             try {  
    154.                 book.write(o);  
    155.             } catch (Exception ex) {  
    156.                 ex.printStackTrace();  
    157.             } finally {  
    158.                 o.flush();  
    159.                 o.close();  
    160.             }  
    161.         }  
    162.         File srcfile[] = new File[fileNames.size()];  
    163.         for (int i = 0, n = fileNames.size(); i < n; i++) {  
    164.             srcfile[i] = new File(fileNames.get(i));  
    165.         }  
    166.         util.FileZip.ZipFiles(srcfile, zip);  
    167.         FileInputStream inStream = new FileInputStream(zip);  
    168.         byte[] buf = new byte[4096];  
    169.         int readLength;  
    170.         while (((readLength = inStream.read(buf)) != -1)) {  
    171.             out.write(buf, 0, readLength);  
    172.         }  
    173.         inStream.close();  
    174.     }  
    175. }  

    最后还有个工具类package util;

    压缩工具类代码  收藏代码
    1. import java.io.FileInputStream;  
    2. import java.io.FileOutputStream;  
    3. import java.io.IOException;  
    4. import java.util.zip.ZipEntry;  
    5. import java.util.zip.ZipOutputStream;  
    6. /**  
    7.  *   
    8.  * @author http://javaflex.iteye.com/  
    9.  *  
    10.  */  
    11. public class FileZip {  
    12.     /**  
    13.      *   
    14.      * @param srcfile 文件名数组  
    15.      * @param zipfile 压缩后文件  
    16.      */  
    17.     public static void ZipFiles(java.io.File[] srcfile, java.io.File zipfile) {  
    18.         byte[] buf = new byte[1024];  
    19.         try {  
    20.             ZipOutputStream out = new ZipOutputStream(new FileOutputStream(  
    21.                     zipfile));  
    22.             for (int i = 0; i < srcfile.length; i++) {  
    23.                 FileInputStream in = new FileInputStream(srcfile[i]);  
    24.                 out.putNextEntry(new ZipEntry(srcfile[i].getName()));  
    25.                 int len;  
    26.                 while ((len = in.read(buf)) > 0) {  
    27.                     out.write(buf, 0, len);  
    28.                 }  
    29.                 out.closeEntry();  
    30.                 in.close();  
    31.             }  
    32.             out.close();  
    33.         } catch (IOException e) {  
    34.             e.printStackTrace();  
    35.         }  
    36.     }  
    37. }  

    OK全部内容完成



     

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

    以后记得代码加注释

     

    亲,记得给个评论哦

    • 大小: 4.4 KB
    • 大小: 2.5 KB
    • POI.rar (5.7 MB)
    • 下载次数: 1449
    展开全文
  • java 大数据EXCEL导出

    2018-04-20 15:00:28
    1、需要加载以下三个包使用XSSFWorkbook 实现大数据导出,将数据分批从数据库取出,比如一次1万条,然后按顺序生成相应的EXCEL文件,再通过压缩处理,将生成的EXCEL文件压缩为ZIP包,下载该包poi-ooxml-3.17.jar、...

    1、需要加载以下三个包

    使用XSSFWorkbook 实现大数据导出,将数据分批从数据库取出,比如一次1万条,然后按顺序生成相应的EXCEL文件,再通过压缩处理,将生成的EXCEL文件压缩为ZIP包,下载该包

    poi-ooxml-3.17.jar、poi-3.17.jar、hutool-all-4.0jar

    在项目的pom.xml的dependencies中加入以下内容:
    <!-- https://mvnrepository.com/artifact/org.apache.poi/poi -->
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi</artifactId>
        <version>3.17</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml -->
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-ooxml</artifactId>
        <version>3.17</version>
    </dependency>
    <dependency>
        <groupId>cn.hutool</groupId>
        <artifactId>hutool-all</artifactId>
        <version>4.0.9</version>

    </dependency>

    2、实现生成EXCEL文件类
    /**
    * 生成EXCEL文件
    * @param fileName 文件名称
    * @param path 所在服务器路径
    * @param headers 标题

    * @param list 数据列表
    * @throws Exception
    */

    public static void createExcel(String fileName,String path,String[] headers,List<Object[]> list) throws Exception{
    XSSFWorkbook workbook = new XSSFWorkbook();
            SXSSFWorkbook sxssfWorkbook = new SXSSFWorkbook(workbook, 100);
            
            Sheet sheet = sxssfWorkbook.createSheet("sheet");
            Row row = sheet.createRow(0);


            for(int i=0;i<headers.length;i++){
                row.createCell(i).setCellValue(headers[i]);
            }
            
            int k =1;
            for(Object[] l : list){//行
                row = sheet.createRow(k++);
                
                int c = 0;
            for(Object o:l){//列
            CellUtil.createCell(row, c++, String.valueOf(o));
            }
            }
            FileOutputStream out = new FileOutputStream(path+fileName);
            sxssfWorkbook.write(out);
            out.close();

    }

    3、生成ZIP包,并将excel文件删除
    public static void main(String[] args) throws Exception {
    Date d = new Date();
    String basePath = "d:/excelzip/";
    String path = basePath+UUID.randomUUID().toString()+"/";
    File dir = new File(path);
    if(!dir.exists()){
    dir.mkdir();
    }

    String fileName = "wb";
    //表头
    String[] headers = {"ID","NAME","EMAIL","SCORE"};
    //数据
    for(int i=1;i<4;i++){
    List<Object []> list = new ArrayList<Object[]>();
    for(int j=1;j<10000;j++){
    Object[] o = {i*10000+j,i+"-A-"+j,"A"+j+"@qq.com",Math.random()};
    list.add(o);
    }
    createExcel(fileName+"_"+i+".xlsx",path,headers,list);
    }


    ZipUtil.zip(path,basePath+fileName+".zip");
    FileUtils.deleteDirectory(dir);

            System.out.println(new Date().getTime()-d.getTime());

    }

    4、通过浏览器下载
    public ModelAndView down(HttpServletRequest request,
    HttpServletResponse response) throws IOException {
    String fileName = "wb";
    OutputStream  out = response.getOutputStream();  
    response.reset();// 清空输出流  
            response.setContentType("application/octet-stream;charset=UTF-8");  
            response.setHeader("Content-Disposition", "attachment;filename="  
                    +new String(fileName.getBytes("GB2312"), "8859_1")  
                    + ".zip");  
            response.addHeader("Pargam", "no-cache");  
            response.addHeader("Cache-Control", "no-cache");  
            
    File zip = new File("d:/excelzip/wb.zip");


       FileInputStream inStream = new FileInputStream(zip);          
       byte[] buf = new byte[4096];  
       int readLenght;  
       while((readLenght = inStream.read(buf)) != -1 ){  
           out.write(buf,0,readLenght);  
       }  
       inStream.close();     
       out.close();  
        return null;
    }

    展开全文
  • java中使用poi导出Excel大批量数据 存在两个导出方法:存在一个分批量导出ZIP文件,一个导出exel文件
  • 使用poi导出excel支持xls、xlsx格式大数据导出java工具类,支持同一个单元格不同文本格式。找了好久,加上自己修改后,调试通过,发布出来分享,(调整student类位置)包含所需jar包,工具类,使用示例
  • 使用POI导出大数据量到EXCEL
  • 最近公司一个06年统计项目在导出Excel时造成应用...随后在网上查阅了部分资料只是在POI大数据导出API的基础上写的demo示例无任何参考价值…解决内存溢出常用方法就是打开GC日志{Heap before GC invocations=29 (full
  • excel导出,如果数据量在百万级,会出现俩点内存溢出的问题: 1. 查询数据量过大,导致内存溢出。 该问题可以通过分批查询来解决; 2. 最后下载的时候大EXCEL转换的输出流内存溢出;该方式可以通过新版的...
  • poi导出大数据 1000万

    2017-07-04 16:10:50
    poi大数据导出,千万数据导出,不会内存溢出。
  • poi大数据导出excel

    2019-08-02 14:49:48
    由于本人采取的是利用反射的方式,这样的好处,可以兼容,导出所有类型的数据,例如,订单,充值记录等等。 既然是公有的接口,肯定有一定的约束规范。 (1)导出的表头需要自己设置一个动态数组 (2) 头部的宽度...
  • POI 导入导出功能,引用jar包是关键,maven依赖支持1.37版. 介绍: 首先,理解一下一个Excel的文件的组织形式,一个Excel文件对应于一个workbook(HSSFWorkbook),一个workbook可以有多个sheet(页/表)...
  • Springboot+poi导出Excel

    2019-03-21 16:44:22
    Springboot+poi导出Excel 一、引入jar包 注意需要引入3.8版本,POI3.8提供了SXSSFWorkbook类,来处理大数据内存溢出的问题.可设置默认内存大小,多出的部分可存入硬盘中,不会内存溢出. <!-- poi依赖 --> <...
  • POI导出大数据量excel(注:项目源码及后续更新请点击)1、ExcelUtils类:package Utils; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import org.apache.poi.common....
  • Java POI处理大量数据导入导出xls和xlsx导入数据(大量)导出数据(大量)总结 xls和xlsx xls是旧版Excel格式文件,xlsx是新版Excel格式文件;而xlsx新版格式其实是一系列文件压缩包, 如图: xls是以二进制的方式...
  • poi导出大数据,先生成多个excel在生成一个jar包
  • poi导出excel最常用的是第一种方式HSSFWorkbook,不过这种方式数据量大的话会产生内存溢出问题,SXSSFWorkbook是一种大数据量导出格式,csv是另一种excel导出的一种轻快的实现。 先介绍一下这三种格式的特点 1...
  • POI 提供了 好几种生成Excel的方式,查看官方的API可以发现 第一种:HSSFWorkbook  针对是 EXCEL2003 版本,扩展名为 .xls;所以 此种的局限就是 导出的行数 至多为 65535 行,此种 因为行数不足七万行 所以 一般...
  • 导出数据是一个应用常用的功能,而使用java语言时常用的工具类莫过于POI。不过当数据量很大时,会经常遇到OOM的问题。通过两天尝试,终于解决了OOM的问题,以下分享一下解决过程。 优化1:首先,我们对导出文件的...
1 2 3 4 5 ... 20
收藏数 707
精华内容 282