用大量数据更新ppt幻灯片中嵌入的excel文件apache poi

问题描述 投票:0回答:1

我正在尝试更新嵌入在 ppt 幻灯片中的空 excel,并且正在使用小尺寸 excel 文件,但是使用包含更多数据的 excel 文件会引发错误:更新 xssfworkbook 超出了 gc 开销限制

我当前的代码是这样的:

            PackagePart embeddedFile = null;
        for (PackagePart packagePart : ppt.getAllEmbeddedParts()) {
            if ("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet".equalsIgnoreCase(packagePart.getContentType())) {
                firstEmbeddedExcelPackagePart = packagePart;
            }
        }

        if (embeddedFile != null) {
            InputStream inputStream = getExcelInputStream();
            XSSFWorkbook workbook = new XSSFWorkbook(inputStream);
            OutputStream os = firstEmbeddedExcelPackagePart.getOutputStream();
            workbook.write(os);
            workbook.close();
            os.close();
        }

然后我尝试通过在上面的一行中执行此更新来解决该错误,但得到了这个新错误 java.lang.OutOfMemoryError: Java heap space

.... 
SXSSFWorkbook workbook = new SXSSFWorkbook(new XSSFWorkbook(inputStream), 100, true, true);
...

然后尝试通过更新此值-Xmx8192m来更新intellij中的jvm配置,但得到了相同的第一个错误。

有没有办法处理大尺寸的 Excel 文件,以便更新 ppt 幻灯片(空文件)中现有的嵌入 Excel 文件,或者选择创建要嵌入的文件而不是更新模板 Excel 文件?

谢谢您的回答。

java apache-poi
1个回答
0
投票

请参阅 错误 java.lang.OutOfMemoryError:超出 GC 开销限制,原因为

java.lang.OutOfMemoryError: GC overhead limit exceeded

此消息意味着由于某种原因垃圾收集器正在运行 花费过多的时间......并且恢复很少的记忆 在每次运行中。

我见过这种情况发生的罕见情况是 一些代码创建了大量的临时对象和大量的 内存已经非常有限的弱引用对象 环境。

这里也是如此。

我想您的代码的完整示例类似于我在 Updateembedded worksheet in ppt Slide apache poi中的答案。

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.OutputStream;

import org.apache.poi.xslf.usermodel.*;

import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.openxml4j.opc.PackagePart;

public class PPTXReplaceEmbeddedExcel {
         
 public static void main(String[] args)  {

  try ( XMLSlideShow slideShow = new XMLSlideShow(new FileInputStream("./TableSample.pptx"));
        FileOutputStream out = new FileOutputStream("./TableSampleNew.pptx"); ) {
  
   PackagePart firstEmbeddedExcelPackagePart = null;
   for (PackagePart packagePart : slideShow.getAllEmbeddedParts()) {
    System.out.println(packagePart.getContentType());
    if ("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet".equals(packagePart.getContentType())) {
     firstEmbeddedExcelPackagePart = packagePart;
    }
   }
  
   if (firstEmbeddedExcelPackagePart != null) {
    try ( FileInputStream fis = new FileInputStream("./Excel.xlsx");
          XSSFWorkbook workbook = new XSSFWorkbook(fis);
          OutputStream os = firstEmbeddedExcelPackagePart.getOutputStream(); ) {
     // do something with workbook...
     workbook.write(os);
    }
   }
    
   slideShow.write(out);
  } catch (Exception ex) {
   ex.printStackTrace();
  }
 }
}

那里

XMLSlideShow slideShow = new XMLSlideShow(new FileInputStream("./TableSample.pptx"))
从 Office Open XML 文件格式的 PowerPoint 文件创建 XMLSlideShow。这意味着解压缩 Office Open XML 文件格式 ZIP、读取 XML 并创建大量 Java 对象(Apache POI
XSLF
对象,以及从 PowerPoint 文件的 MIcrosofts XML 模式创建的大量
XMLBeans
对象)。之后,
XSSFWorkbook workbook = new XSSFWorkbook(fis)
对 Office Open XML 文件格式的 Excel 文件中的
XSSFWorkbook
执行相同的操作。这意味着解压缩 Office Open XML 文件格式 ZIP、读取 XML 并创建大量 Java 对象(Apache POI
XSSF
对象,以及从 Excel 文件的 MIcrosofts XML 架构创建的大量
XMLBeans
对象)。

毕竟,我们在内存中拥有大量用于

XSLF
XSSF
的 Java 对象,以及通过
XMLBeans
从 Microsoft 用于 PowerPoint 和 Excel 的 XML 方案创建的两种低级 Java 对象。

这会消耗内存和CPU。

如果只是从 Excel 文件的全部内容更新

firstEmbeddedExcelPackagePart
而不操作工作簿,则不需要创建
XSSFWorkbook
。然后您只需将Excel文件内容复制到嵌入包部分的
OutputStream
即可。这至少省去了创建
XSSFWorkbook
的麻烦。

...
if (firstEmbeddedExcelPackagePart != null) {
 try ( FileInputStream fis = new FileInputStream("./Excel.xlsx");
       //XSSFWorkbook workbook = new XSSFWorkbook(fis);
       OutputStream os = firstEmbeddedExcelPackagePart.getOutputStream(); ) {
  // do something with workbook...
  //workbook.write(os);
   fis.transferTo(os);
  
 }
}
...
© www.soinside.com 2019 - 2024. All rights reserved.