首页 技术 正文
技术 2022年11月15日
0 收藏 801 点赞 4,537 浏览 4849 个字

  最近在利用poi往excel中写入大量数据时,发现excel2003最多只支持65535条,大量数据时容易造成oom,上网查了一下api,发现目前对于2003,每个sheet最多支持65535条,若数据量远超65535,建议分sheet处理,而poi3.8之后,出现了SXSSFWorkbook,可以支持大数据量的写入excel操作,但是目前只支持excel2007

HSSF是POI工程对Excel 97(-2007)文件操作的纯Java实现
XSSF是POI工程对Excel 2007 OOXML (.xlsx)文件操作的纯Java实现

从POI 3.8版本开始,提供了一种基于XSSF的低内存占用的API—-SXSSF

SXSSF通过一个滑动窗口来限制访问Row的数量从而达到低内存占用的目录,XSSF可以访问所有行。旧的行数据不再出现在滑动窗口中并变得无法访问,与此同时写到磁盘上。
在自动刷新的模式下,可以指定窗口中访问Row的数量,从而在内存中保持一定数量的Row。当达到这一数量时,在窗口中产生新的Row数据,并将低索引的数据从窗口中移动到磁盘中。
或者,滑动窗口的行数可以设定成自动增长的。它可以根据需要周期的根据一次明确的flushRow(int keepRows)调用来进行修改。

SXSSF (Streaming Usermodel API)

SXSSF (package: org.apache.poi.xssf.streaming) is an API-compatible streaming extension of XSSF to be used when very large spreadsheets have to be produced, and heap space is limited. SXSSF achieves its low memory footprint by limiting access to the rows that are within a sliding window, while XSSF gives access to all rows in the document. Older rows that are no longer in the window become inaccessible, as they are written to the disk.

You can specify the window size at workbook construction time via new SXSSFWorkbook(int windowSize) or you can set it per-sheet via SXSSFSheet#setRandomAccessWindowSize(int windowSize)

When a new row is created via createRow() and the total number of unflushed records would exceed the specified window size, then the row with the lowest index value is flushed and cannot be accessed via getRow() anymore.

The default window size is 100 and defined by SXSSFWorkbook.DEFAULT_WINDOW_SIZE.

A windowSize of -1 indicates unlimited access. In this case all records that have not been flushed by a call to flushRows() are available for random access.

Note that SXSSF allocates temporary files that you must always clean up explicitly, by calling the dispose method.

SXSSFWorkbook defaults to using inline strings instead of a shared strings table. This is very efficient, since no document content needs to be kept in memory, but is also known to produce documents that are incompatible with some clients. With shared strings enabled all unique strings in the document has to be kept in memory. Depending on your document content this could use a lot more resources than with shared strings disabled.

Carefully review your memory budget and compatibility needs before deciding whether to enable shared strings or not.

The example below writes a sheet with a window of 100 rows. When the row count reaches 101, the row with rownum=0 is flushed to disk and removed from memory, when rownum reaches 102 then the row with rownum=1 is flushed, etc.

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 {        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);            }        }        // Rows with rownum < 900 are flushed and not accessible        for(int rownum = 0; rownum < 900; rownum++){          Assert.assertNull(sh.getRow(rownum));//调用了getRow方法,写入到磁盘中,释放了内存        }        // 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();    }

The next example turns off auto-flushing (windowSize=-1) and the code manually controls how portions of data are written to disk

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 {        SXSSFWorkbook wb = new SXSSFWorkbook(-1); // turn off auto-flushing and accumulate all rows in memory        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);            }           // manually control how rows are flushed to disk           if(rownum % 100 == 0) {                ((SXSSFSheet)sh).flushRows(100); // retain 100 last rows and flush all others                // ((SXSSFSheet)sh).flushRows() is a shortcut for ((SXSSFSheet)sh).flushRows(0),                // this method flushes all rows           }        }        FileOutputStream out = new FileOutputStream("/temp/sxssf.xlsx");        wb.write(out);        out.close();        // dispose of temporary files backing this workbook on disk        wb.dispose();   }

SXSSF flushes sheet data in temporary files (a temp file per sheet) and the size of these temporary files can grow to a very large value. For example, for a 20 MB csv data the size of the temp xml becomes more than a gigabyte. If the size of the temp files is an issue, you can tell SXSSF to use gzip compression:

  SXSSFWorkbook wb = new SXSSFWorkbook();  wb.setCompressTempFiles(true); // temp files will be gzipped以上内容来自API及个人总结,详见源API    http://poi.apache.org/spreadsheet/how-to.html
相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:8,999
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,511
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,357
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,140
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,770
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,848