在Java中将文件导出为xlsx格式
问题的原因是Apache POI在写入大文件时会将所有数据保存在内存中,这会消耗大量的内存资源。解决方法是使用POI的streaming API,并指示POI逐步刷新数据。
下面是一个来自POI网站的示例:
public static void main(String[] args) throws Throwable { SXSSFWorkbook wb = new SXSSFWorkbook(100); // 在内存中保留100行数据,超过的行将被刷新到磁盘 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); } } // 行号小于900的行被刷新并不可访问 for(int rownum = 0; rownum < 900; rownum++){ Assert.assertNull(sh.getRow(rownum)); } // 最后100行仍然在内存中 for(int rownum = 900; rownum < 1000; rownum++){ Assert.assertNotNull(sh.getRow(rownum)); } FileOutputStream out = new FileOutputStream("/temp/sxssf.xlsx"); wb.write(out); out.close(); // 清理临时文件 wb.dispose(); }
Apache POI是开源的,正是你用来创建Excel文件的工具。可以查看包名。
参考Apache POI的网站(SXSSF (Streaming Usermodel API)部分)获取更多信息。
使用POI来流式处理数据是一件痛苦的事情,因为它能做的最好的就是将数据暂存到磁盘上,然后在你完成后与其余部分结合,它不能在输入到达时直接流式传输到输出。
POI还存在其他问题:
- 它占用很多内存。
- 对于我期望它在整体要求中只是一个很小部分的东西来说,它有相当大的一套依赖。
- 它不够快。
- 它很容易生成损坏的文件。
对这些不足之处的反驳是,它允许你在Java中对OOXML文件做任何事情,并且是唯一能做到这一点的东西。
我有一些(内部)项目使用POI来导出XLSX数据,并且正在开发另一个项目,我很想避免使用POI。
我遇到了这个问题:如何创建和写入Excel文件(.xlsx)?,并且受到了给出的答案的启发,产生了这个:https://github.com/Yaytay/streaming-xlsx-writer
它的作用只是将单个工作表的XLSX文件作为数据流式传输到OutputStream。
它提供了一些基本的格式化选项(如果需要更多,请随时提问)。
它几乎没有内存开销,并且没有任何依赖关系。