21

我在我的 J2EE Web 应用程序中使用 POI 来生成工作簿。但是,我发现 POI 需要大约 3 分钟来创建一个包含 25K 行的工作簿(每行大约 15 列)。这是 POI 性能问题,还是花这么多时间是合理的?还有其他以更好的性能而闻名的 API 吗?

4

5 回答 5

21

如果您使用“流式”POI API 而不是标准 API,则使用 POI 写入大文件的性能会大大降低。事实上,默认情况下,POI 会将您的所有数据保存在内存中,然后在最后一口气写入。对于大文件来说,它的内存占用可能非常大。相反,使用流 API,您可以控制内存的使用方式以及数据如何逐渐写入磁盘。

为了创建流式工作簿,请使用以下内容:

  SXSSFWorkbook book = new SXSSFWorkbook(); 
  book.setCompressTempFiles(true);

  SXSSFSheet sheet = (SXSSFSheet) book.createSheet();
  sheet.setRandomAccessWindowSize(100);// keep 100 rows in memory, exceeding rows will be flushed to disk
  // ...
于 2014-07-07T11:49:19.590 回答
14

看到 POI 花费这么多时间来生成这样的文件,我会感到非常惊讶。我刚刚在大约 18 秒内生成了一张包含 30000 行 x 10 个单元格的表格(公平地说,没有格式化)。原因可能是以下之一:

  • POI 日志记录可能已打开,如此处所述
  • 您正在从交换内存运行
  • 您的 VM 可用堆可能非常低
于 2010-03-23T09:42:13.267 回答
3

如果其他答案都不起作用,看看 Andy Khan 的 JExcel 是否会更好。我发现它在处理 Java 中的 Excel 方面远远优于 POI。

于 2010-03-23T10:00:30.130 回答
1

我们还在我们的网络应用程序中使用 POI,并且没有任何性能问题 - 尽管我们生成的文档比您的要小得多。我会首先检查 POI 是否是这里的真正问题。尝试在没有 J2EE 开销(单元测试)的情况下生成这些文档并测量性能。您还可以监视 J2EE 服务器上的负载和内存使用情况,以查看问题是否来自某些次优的系统设置。

于 2010-03-23T09:46:37.523 回答
1

我已经将 Apache POI 与 JExcel 库进行了比较。JExcel 似乎比 Apache POI 快 4 倍,但内存消耗似乎或多或少相同:

@Test
public void createJExcelWorkbook() throws Exception {
        WritableWorkbook workbook = Workbook.createWorkbook(new File("jexcel_workbook.xls"));
        WritableSheet sheet = workbook.createSheet("sheet", 0); 
        for ( int i=0; i < 65535; i++) {
            for ( int j=0; j < 10; j++) {
                Label label = new Label(j, i, "some text " + i + " " + j);
                sheet.addCell(label);
            }
        }
        workbook.write();
        workbook.close();
}

@Test
public void createPoiWorkbook() throws Exception {
    Workbook wb = new HSSFWorkbook();
    Sheet sheet = wb.createSheet("sheet");  
    for ( int i=0; i < 65535; i++) {
        Row row = sheet.createRow(i);
        for ( int j=0; j < 10; j++) {
            Cell cell = row.createCell(j);
             cell.setCellValue("some text " + i + " " + j);
        }
    }   
    FileOutputStream fileOut = new FileOutputStream("poi_workbook.xls");
    wb.write(fileOut);
    fileOut.close();
}

我已经使用 JExcel 2.6.12 版和 Apache POI 3.7 版对其进行了测试。您需要自己下载最新的库版本并运行上面的简单测试以获得更准确的数字。

<dependency org="org.apache.poi" name="poi" rev="3.7"/>
<dependency org="net.sourceforge.jexcelapi" name="jxl" rev="2.6.12"/>

注意: Apache POI 的限制为每张纸 65535 行。

于 2012-01-04T14:13:24.377 回答