用于阅读的Apache POI Streaming(SXSSF)

bru*_*_cw 14 java apache-poi

我需要读取大型excel文件并将其数据导入我的应用程序.

由于POI占用了大量的堆来工作,经常抛出OutOfMemory错误,我发现有一个Streaming API用于以串行方式处理excel数据(而不是将文件完全加载到内存中)

我创建了一个xlsx工作簿,只有一个工作表,并在单元格中输入了几个值,并提出以下代码来尝试阅读它:

public static void main(String[] args) throws Throwable {
    // keep 100 rows in memory, exceeding rows will be flushed to disk
    SXSSFWorkbook wb = new SXSSFWorkbook(new XSSFWorkbook(new FileInputStream("C:\\test\\tst.xlsx")));
    SXSSFSheet sheet = (SXSSFSheet) wb.getSheetAt(0);
    Row row = sheet.getRow(0);
    //row is always null
    while(row.iterator().hasNext()){ //-> NullPointerException
        System.out.println(row.getCell(0).getStringCellValue());
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,尽管能够正确获取其工作表,但它总是带有empty(null)行.

我已经研究并在互联网上找到了几个Streaming API的例子,但没有一个是关于读取现有文件的,它们都是关于生成excel文件的.

实际上是否可以从.xlsx流中的现有文件中读取数据?

bru*_*_cw 28

在挖掘了更多之后,我发现了这个:

如果您以前使用过Apache POI来读取Excel文件,您可能会注意到它的内存效率不高.读取整个工作簿会导致严重的内存使用量激增,这会对服务器造成严重破坏.

有很多很好的理由说明为什么Apache必须读取整个工作簿,但大多数都与库允许您使用随机地址进行读写这一事实有关.如果(并且仅当)您只想以快速且内存有效的方式读取Excel文件的内容,您可能不需要此功能.不幸的是,POI库中唯一用于读取流式工作簿的东西需要您的代码使用类似SAX的解析器.该API缺少所有友好的类,如Row和Cell.

该库充当流式API的包装器,同时保留了标准POI API的语法.请继续阅读,看看它是否适合您.

InputStream is = new FileInputStream(new File("/path/to/workbook.xlsx"));
StreamingReader reader = StreamingReader.builder()
        .rowCacheSize(100)    // number of rows to keep in memory (defaults to 10)
        .bufferSize(4096)     // buffer size to use when reading InputStream to file (defaults to 1024)
        .sheetIndex(0)        // index of sheet to use (defaults to 0)
        .sheetName("sheet1")  // name of sheet to use (overrides sheetIndex)
        .read(is);            // InputStream or File for XLSX file (required)
Run Code Online (Sandbox Code Playgroud)

还有SAX Event API,它读取文档并通过事件解析其内容.

如果内存占用是个问题,那么对于XSSF,您可以获取基础XML数据并自行处理.这适用于愿意学习.xlsx文件的一些低级结构的中间开发人员,以及在java中处理XML的人.它使用起来比较简单,但需要对文件结构有基本的了解.提供的优点是您可以读取内存占用相对较小的XLSX文件.

  • @Dojo SXSSF 仅支持写入,不支持读取。 (2认同)