【问题标题】:converting excel to XSSFWorkbook using Apache poi taking long time使用 Apache poi 将 excel 转换为 XSSFWorkbook 需要很长时间
【发布时间】:2017-09-09 14:27:50
【问题描述】:

我正在尝试将 excel 文件转换为 XSSFWorkbook ,我有大约 7000 行和大约 145 列。在我下面的代码中,将 excel 文件转换为第 2 行的 XSSFWorkbook 大约需要 15 分钟:-

InputStream fs = new FileInputStream(filename);   // (1)
XSSFWorkbook wb = new XSSFWorkbook(fs);           // (2)
XSSFSheet sheet = wb.getSheetAt(0); 

我不想在 XFFSWorkbook 中添加 7000 行,我只想在第 2 行转换时向 XFFSWorkbook 添加 30 行?

如果没有,如何减少将 excel 转换为 XSSFWorkbook 所需的时间?

【问题讨论】:

  • 请更正您的问题。某处你说 7000 行和其他 7000 列
  • 有人可以帮忙解决这个问题吗?
  • 提高文件而不是流的速度。看到这个:stackoverflow.com/a/17542608/338249?stw=2
  • 感谢 rjdkolb 帮助了一点,你能告诉我如何将 StreamingReader 转换为 Workbook (Apache poi)
  • @Peter Osta:仅出于好奇:究竟是什么“帮助了一点”? @rjdkolb 建议在打开Workbook 时使用File 而不是FileInputStream。这“有点帮助”?或者使用Excel Streaming Reader 有点帮助?如果是后者:请阅读Important! Read first! ff。小心。

标签: java excel apache-poi performance-testing fileinputstream


【解决方案1】:

*.xlsx 文件是一个 ZIP 存档,其中包含具有不同 XML 文件的目录结构中的 Excel 的数据。

例如有

  • /xl/workbook.xml 描述基本工作簿结构,
  • /xl/worksheets/sheet1.xml, /xl/worksheets/sheet2.xml, ... /xl/worksheets/sheetN.xml 拥有工作表数据 - 这是行 和单元格,但不是单元格内的所有数据都直接存储 那里。单元格样式也不直接存储在那里。 - ,
  • /xl/styles.xml 包含单元格样式,
  • /xl/sharedStrings.xml 包含单元格的所有字符串内容 所有床单。这是为了避免多次存储相同的字符串 如果此字符串在单元格中多次使用,则为次数。

所以如果你想读取*.xlsxZIP存档,你需要解压ZIP存档,然后至少解析上面提到的四个XML文件来获取XSSFWorkbook的数据。这就是apache poiXSSFWorkbook wb = new XSSFWorkbook(fileinputstream); 所做的。

因此,如果您确实需要 XSSFWorkbook 作为结果,则无法绕过此过程。如果您不怀疑apache poi 编写了显式延迟例程,那么就不可能减少此过程的时间。

您的方法只读取少于存储在工作表中的行数,可能会节省时间。但是你的结果将是一个 XSSFWorkbook 包含所有样式和所有字符串内容,但只有一些与这些样式和字符串数据相关的工作表数据。所以它会导致XSSFWorkbook 部分损坏。这就是为什么没有人真正考虑过这种方法的原因。

仅当要求仅从/xl/worksheets/sheetN.xml 之一读取纯无格式数据而不 创建XSSFWorkbook,那么您只需要解压缩ZIP 存档,然后仅解析所需的/xl/worksheets/sheetN.xml/xl/sharedStrings.xml 从中获取单元格的字符串内容。与上述整个过程相比,这将在更短的时间内成为可能。

【讨论】:

    【解决方案2】:

    要在处理非常大的文件时略微提高性能,只需将文件直接传递到工作簿而不是流。

    来自link

    打开工作簿时,可以是 .xls HSSFWorkbook,也可以是 .xlsx XSSFWorkbook,工作簿可以从文件或 输入流。使用 File 对象可以降低内存消耗, 而 InputStream 需要更多内存,因为它必须缓冲 整个文件。

    XSSFWorkbook wb = new 
    XSSFWorkbook(new File (filename));           // (2)
    XSSFSheet sheet = wb.getSheetAt(0);
    

    此外,使用 WorkBookFactory 更简洁,因为它抽象了您正在使用的 excel 文件的类型:

    Workbook workbook = WorkbookFactory.create(new File(filename));
    

    【讨论】:

    • 使用File 代替FileInputStream 的问题是您不能将XSSFWorkbook 上的更改写入同一个文件filename
    • 我想这可能是个问题。我用模板写报告,所以它适合我的用例。
    • 刚刚测试过,使用FileFileInputStream 并没有显着节省时间。这并不奇怪,因为区别仅在于使用File ZipPackage 是直接从File 打开的。在使用FileInputStream 时,通过将整个ZIP 内容读入内存来打开它。所以使用File 可以减少内存占用。但是整个解析过程是一样的。因此,只有在可用内存也较少的情况下才能节省时间。
    猜你喜欢
    • 1970-01-01
    • 2014-06-13
    • 1970-01-01
    • 1970-01-01
    • 2012-06-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多