HSSF与XSSF导出excel文档

Apache POI

Apache POI 是用Java编写的免费开源的跨平台的 Java API,它可以创建和维护操作各种符合Office Open XML(OOXML)标准和微软的OLE 2复合文档格式(OLE2)的Java API。

用它可以使用Java读取和创建,修改MS Excel文件.而且,还可以使用Java读取和创建MS Word和MSPowerPoint文件。Apache POI 提供Java操作Excel解决方案(适用于Excel97-2008)。

 

HSSF and XSSF for Excel Documents

需要以下jar

<!-- office文档组件 -->
        <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>
        <dependency>
            <groupId>org.apache.xmlbeans</groupId>
            <artifactId>xmlbeans</artifactId>
            <version>2.4.0</version>
        </dependency>

 

 

一、HSSF:支持 excel97—2003之间的,(.xls)

注意:97—2003excel一个sheet最多65536行。

 

创建步骤:

1、New Workbook//创建一个工作簿

2、New Sheet//创建一个工作表

3、createRow//创建一个行

4、row.createCell(index)//index是指定哪一列

5、cell.setCellValue(1);//向单元格设置内容

分析:WriteExcelHSSF 的代码

是按照上边步骤执行,最后进行写操作。

测试代码:

 1 package yycg.poi;
 2 
 3 import org.apache.poi.hssf.usermodel.HSSFWorkbook;
 4 import org.apache.poi.ss.usermodel.Cell;
 5 import org.apache.poi.ss.usermodel.Row;
 6 import org.apache.poi.ss.usermodel.Sheet;
 7 import org.apache.poi.ss.usermodel.Workbook;
 8 
 9 import java.io.FileOutputStream;
10 
11 /**
12  * poi测试导出excel文件,数据量大出现内存溢出
13  */
14 public class WriteExcelHSSF {
15     public static void main(String[] args) throws Exception {
16         //创建一个文件输出 流
17         FileOutputStream out = new FileOutputStream("d:/workbook.xls");
18         //创建一个工作薄
19         Workbook wb = new HSSFWorkbook();
20         for (int j = 0; j < 11; j++) {
21             Sheet s = wb.createSheet();//创建一个sheet
22             wb.setSheetName(j, "sheet"+j);//指定sheet的名称
23             //xls文件最大支持65536行
24             for (int rownum = 0; rownum < 65536; rownum++) {//创建行,.xls一个sheet中的行数最大65535
25                 //创建一行
26                 Row row = s.createRow(rownum);
27                 for (int cellnum = 0; cellnum < 10; cellnum++) {//一行创建10个单元格
28                     // 在行里边创建单元格
29                     Cell cell = row.createCell(cellnum);
30                     //向单元格写入数据
31                     cell.setCellValue(cellnum);
32                 }
33             }
34         }
35         System.out.println("int .......");
36         wb.write(out);//输出 文件内容
37 
38         try {
39             Thread.sleep(2000);
40         }catch (InterruptedException e){
41             e.printStackTrace();
42         }
43         out.close();
44         System.out.println("创建excel文件成功!。。。。。。。。。。。。");
45     }
46 }

 

 

通过执行大数据抛出异常:

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space

内存溢出

 

总结:HSSF 在使用将excel数据加载到内容再写磁盘,如果是大数据量操作,会导致内存溢出。

 

 

二、XSSF:支持2007以上版本,Excel 2007 OOXML (.xlsx)

excel文件格式是基于是xml存储,这是与03版本最大的区别。

XSSF对HSSF性能更好,对内存消耗不高。

 

可以解决HSSF操作大数据内存溢出问题。

 

原理:

在创建XSSFworkbook时需要设置构造函数的参数:

SXSSFWorkbook wb = new SXSSFWorkbook(-1); //设置为-1,关闭自动写入磁盘时机,由手动进行控制

SXSSFWorkbook wb = new SXSSFWorkbook(100); //SXSSF设置100表示,只保持100个记录在内存,超过记录则写入磁盘。

创建workbook的过程和HSSF一样,先后创建workbook、sheet、row、cell

测试代码如下:

package yycg.poi;

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.SXSSFSheet;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;

import java.io.FileOutputStream;

public class WriterExcelXSSF1 {
    public static void main(String[] args) throws  Exception{
        //创建一个SXSSFWorkbook
        //关闭自动刷新
        SXSSFWorkbook wb = new SXSSFWorkbook(-1);
        //创建一sheet
        Sheet sheet = wb.createSheet();
        for(int rownum=0;rownum<100000;rownum++){
            //创建一个行
            Row row = sheet.createRow(rownum);
            for (int cellnum=0;cellnum<10;cellnum++){
                //创建单元格
                Cell cell = row.createCell(cellnum);
                //单元格地址
                String adress = new CellReference(cell).formatAsString();
                cell.setCellValue(adress);//向单元格中写入数据
            }
            //手动控制行刷新到磁盘的方式
            if (rownum%10000==0){//一万行向磁盘写一次
                ((SXSSFSheet)sheet).flushRows(100);//保留最后100行并刷新所有其他行
                //Thread.sleep(1000);
                System.out.println("写入....");
                // ((SXSSFSheet)sh).flushRows() is a shortcut for ((SXSSFSheet)sh).flushRows(0),
                // this method flushes all rows
            }
        }

        FileOutputStream out=new FileOutputStream("d:/testxssf.xlsx");
        wb.write(out);//将临时文件合并,写入最终文件
        out.close();
        wb.dispose();
    }
}

 

 

package yycg.poi;

import java.io.FileOutputStream;


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;

public class WriteExcelSXSSF2 {

    public static void main(String[] args) throws Throwable {
        SXSSFWorkbook 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 < 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);
            }

        }

        FileOutputStream out = new FileOutputStream("d:/test2222.xlsx");
        wb.write(out);
        out.close();

        // dispose of temporary files backing this workbook on disk
        wb.dispose();
    }

}

 

 

通过跟踪发现,使用XSSF在导出大数据时,手动控制进行写磁盘,写在了临时文件中,我的电脑是:

(C:\Users\Thinkpad\AppData\Local\Temp\poi-sxssf-sheet1910970138657434208.xml 该目录有很多临时文件)

 

最终待导出完成将临时合并成最终文件写入磁盘。

 

总结:使用XSSF导出数据,将数据写入内存一部分,超过的则立即写磁盘,所以内存占有量有限不会导致内存溢出。

 

posted @ 2018-08-16 22:55  Kmily_Lee  阅读(2313)  评论(0编辑  收藏  举报