当前位置: 首页 > 面试题库 >

Apache POI流式传输(SXSSF)用于阅读

闻人高卓
2023-03-14
问题内容

我需要读取大型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());
    }
}

但是,尽管能够正确获取其工作表,但它始终带有空(null)行。

我已经研究并找到了Internet上Streaming API的几个示例,但是它们都与 读取 现有文件无关,它们都与生成excel文件有关。

实际上是否可以从.xlsx流中的现有文件中读取html" target="_blank">数据?


问题答案:

在深入研究之后,我发现了这个库:

如果您过去使用过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)

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

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



 类似资料:
  • 我需要读取大型excel文件并将它们的数据导入到我的应用程序中。 我在互联网上研究并找到了几个流式API的例子,但它们都不是关于读取现有文件的,它们都是关于生成excel文件的。 实际上是否可以从流中现有的文件中读取数据?

  • 我目前正在使用java。尼奥。频道选择器 问题-调用选择器的选择方法只返回一个值 问:我需要在每次读/写后调用SocketChannel上的关闭吗(我希望不是!)?如果没有,SocketChannel对任何读/写操作都不可用的原因是什么? 很抱歉,我不能发布代码,但我希望我已经清楚地解释了这个问题,有人可以提供帮助。我已经搜索了答案,我发现你不能在SocketChannel连接关闭后重新使用它,但

  • 问题内容: 我有一个200MB的文件,想通过下载提供给用户。但是,由于我们希望用户仅下载一次此文件,因此我们这样做: 强制下载。但是,这意味着整个文件必须加载到内存中,这通常不起作用。我们如何以每块kb的速度将文件流式传输给他们? 问题答案: 尝试这样的事情

  • 我想知道是否有可能实现2种方式的流式传输使用Spring WebFlow?基本上,我希望让客户端发送服务器接收到的数据通量将它们映射到String,然后返回结果,所有这些都流利地进行,而无需收集数据。我使用RSocket完成了它,但我想知道我是否可以使用超文本传输协议2.0(使用Spring和Project-Retor)获得相同的结果。 试过这样做: 1-客户: 2.服务器: 或者: 或者: 没有

  • 我有以下代码: 我只想模拟这些行,并在,因为我将有多个测试用例,具体取决于行(文件为空,行为空,我只得到一行,我得到几行,等等)。 注意:我使用库访问FTP服务器上的文件,因此方法将作为返回类型,而具有。 我正在使用junit 4.12和mockito 3.1.0 提前感谢!

  • 问题内容: 我正在开发一个使用大型MySQL表的spring应用程序。加载大表时,我得到一个,因为驱动程序试图将整个表加载到应用程序内存中。 我尝试使用 但是然后我打开的每个ResultSet都挂了; 在网上查看时,我发现发生这种情况是因为它尝试在关闭ResultSet之前尝试加载所有未读的行,但事实并非如此,因为我这样做是: 小表(3行)也会发生挂起,如果我不关闭RecordSet(在一种方法中